Tuesday, May 5, 2015

Counting occurrences of a string in Vim

On Stack Overflow, Chase T. points out a most useful item in the Vim help, which relates to counting phrases (strings) in the current buffer, which is usually the current file, which is typically long enough that you’d want a command to save you the trouble of just reading through it yourself looking for matches. I will readily admit that string counting is something I don’t do enough to remember how to do without Googling, and yet which I do just enough that I’ve had to Google it more than once. Mayhap this will help me next time?

Toward the point.

The item is count-items, as in :help count-items. The command is simple enough: it’s none other than :s!

As example:

:%s/sympathy/&/gn

35 matches on 35 lines

:%s/sympathy with sounds/&/gn

1 match on 1 line

(Yes, I’m still using Sir Cowper for an example. His Life is now out, in many splendid ebook formats, by the way—go get it from Gutenberg.org yourself.)

When we last saw :s (:substitute), we didn’t cover every aspect of its operation, for example its flags (we were mostly interested in how it operated on a range). For help in understanding the particular :s incantation used here, we can go to :help :s_flags, or more particularly :help sub-replace-special. There we see:

When the {string} starts with "\=" it is evaluated as an expression, see sub-replace-expression.  You can use that for complex replacement or special characters.

Otherwise these characters in {string} have a special meaning:


[…]

magic    nomagic     action    ~
  &      \&          replaced with the whole matched pattern


The & simply stands for the term we’re searching for, so that if we were actually replacing the term, it would replace it with the term itself. We add the n flag to prevent a substitution, but to see that this is indeed how it works, you can go ahead and run the search command without the n:

 :%s/sympathy with sounds/&/g

You should see nothing happen. If that’s not sufficient to convince you that Something Changed, try running u (undo).

So n tells the command not to replace a match. What else does it do? And why are we getting the number of matches after running the command when normally :s does not tell us how many there were?

[n]    Report the number of matches, do not actually substitute.

Ha ha! It turns out that this is basically just a nifty addition to our trusty search-and-replace command—something to let us know how many times a phrase would be replaced. Lacking any dedicated expression-counting command as we are, it also happens to be our best means of counting occurrences of a string in Vim.


For further fun: Note the filename of the help file in which we find :help count-items. It is:

tips.txt

with the explanatory heading:

Tips and ideas for using Vim

Earthquakes and hotcakes! (This is being written by Mr. Moolenaar himself, after all.) It may not be the hugest file in Vim’s help set, but give it a peek nonetheless.

No comments:

Post a Comment