Self-follow-up: I.
I've just realised I made a careless error in trying to literally reproduce your careless mistake, even though it should have been obvious this was incorrect or at least incomplete. Instead of just :w !grep -c clearly you meant: :w !grep -c abc Though as noted before, that still won't count all same-line instances and thus won't fit the bill. II. I *thought* I'd also now found another way to do this, and actually do this with grep by using sed: :!sed s/abc/abc\n/g % | grep -c abc However, I can't get the newline to work right in OpenBSD's sed. It does work in GNU sed. man sed has this: > The escape sequence \n matches a newline character embedded in the pattern > space. You can't, however, use a literal newline character in an address or > in the substitute command. Now I *thought* \n was NOT considered a literal newline, and that I should thus be able to get this to work, but I'm a little stumped. Googled information suggests that the opposite of what's described in the man page may be true: You CAN use a literal newline, but you can't use \n. But I'm not sure if the googled information is correct and I still haven't figured this one out. In trying to get this to work, I took a FILE that contains a bunch of abc's, sometimes several to a line, sometimes not, and I did this[0]: $ sed s/abc/abc^M/g FILE > DAFTFILE Here ^M *was supposed to be* a literal newline, i.e. I pressed ^V followed by the return key, but readers more alert than me can doubtlessly already see the problem: Apparently ^V[enter] yields a literal carriage return, not a literal newline (^J). That's the case on Linux as well, and I don't know why. One interesting observation, if someone does get this to work, is that this :!sed s/abc/abc\n/g % | grep -c abc is only shorter than this :!cat % | tr '\n' ' ' | awk '{print gsub(/abc/, "")}' if the abc string is short. III. Your new subject line is slightly imprecise, as words are usually whitespace-delimited, and I was "looking for a way to count occurrences of 'abc' in FILE". Not every substring is a word. Thanks for your help, Ian Footnote: [0] I redirected things to DAFTFILE here so I could use vi instead of more misleading tools to look at the contents, because at some point just echoing, catting or tailing the output didn't clearly show the ^M's, and it took a while for me to catch on to how they were a problem. On 04/09/2021, ropers <rop...@gmail.com> wrote: > On 03/09/2021, Marc Chantreux <m...@unistra.fr> wrote: >>> 'abc' in FILE, from within vi. >> >> * % means 'the current file' in vi commands so you can write > > That's helpful; thank you! > >> * | is the command separator >> * grep has a -c flag to count occurrences >> >> so you can write: >> >> :w|grep -c abc % > > That doesn't really fit the bill: > > 1. This error message is produced: 'The grep command is unknown' > > 2. grep only counts the number of lines. If the 'abc' reappears in > the same line, grep won't catch that. My version will, however > crufty, though it's arguably better/shorter/more portable to use your > %: > > :!cat % | tr '\n' ' ' | awk '{print gsub(/abc/, "")}' > > And yes, I did also try > :%!tr '\n' ' ' | awk '{print gsub(/abc/, "")}' > but the problem with that is, it replaces the buffer with the number > of occurrences. So cat it is unless someone can point to something > better. > >> you can also write the content of the buffer to a pipe (my prefered >> solution here): >> >> :w !grep -c > > That produces a grep usage prompt here, along with this message: > 'grep -c: exited with status 2.' > Are you sure you've tested this and that you're using just plain (n)vi? > Also, again, grep -c, which I did know about, is insufficient for > counting every occurrence. I suspect there's prolly s/th better than > my clumsy kludge, but grep -c is not de wey. > >>> Sadly, :E doesn't actually work in vim. It says >>> > E464: Ambiguous use of user-defined command >> >>> I don't know what works in vim. vim prolly has a dozen >>> chrome-electroplated ways to do the same thing, but I don't know them. >> >> :h windows >> >> also: >> >> :h :new >> :h :enew >> :h gf >> :h :bu >> :h :ls >> :h :bw >> >> the following code isfrom my ~/.vimrc so i can: >> * navigate into buffers with <left> and <right> arrows >> * come back to the first buffer with <down> >> * have a fzf menu of the current buffers using <up> >> >> set hidden >> command! -nargs=0 BU redir! > ~/.v.json | silent echo >> json_encode(getbufinfo()) | redir END >> \| silent exec "!vim_BU ~/.v.json ~/.v" >> \|so ~/.v >> \|redraw! >> nnoremap <up> <esc>:BU<cr> >> nnoremap <down> :bfirst!<cr> >> nnoremap <left> :bnext!<cr> >> nnoremap <right> :bprevious!<cr> >> >> the code of vim_BU (i can probably get grid of perl and use jq instead): >> >> vim_BU () { >> perl -MEnv -MJSON -w0 -nE' >> map +( printf "%3s %s%s %s\n" >> , $$_{bufnr} >> , ( $$_{hidden} ? "h" : "a" ) >> , ( $$_{changed} ? "+" : " " ) >> , ( length $$_{name} ? $$_{name} : "NONAME" ) >> ), @{ decode_json $_ } >> ' $1 | fzf | awk '{print "bu "$1}' > $2 >> } > > Wow, that's... helpful(?), I think, but truth be told, I've tested > none of this, because I'm slightly overwhelmed by what to me looks > like far greater complexity than :E, ^W etc. -- and even than my > occurrence-counting one-liner. > > Maybe I'm just not truly ready for vim (though I do use it at times). > >> regards >> marc > > None of the above is intended as throwing anything back in your face > however, and I thank you very much for your reply. > > Kind regards, > Ian > > PS: Regarding this: >> get grid[sic] of perl and use jq > Presumably that's <https://stedolan.github.io/jq/>? > Honestly, I hadn't even heard of jq. > It's not in base; I do see it's in ports, but it's not installed on > any OpenBSD machines I've ever had access to. I see jq is acceptably > licensed, but so long as perl is in base and jq isn't... it makes more > sense for me to learn perl than jq. Because I'm not great with perl > either, but still. >