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 <[email protected]> wrote:
> On 03/09/2021, Marc Chantreux <[email protected]> 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.
>