Se você tem o GNU grep (sempre no Linux e Cygwin, ocasionalmente em outro lugar), você pode conte as linhas de saída de grep -o
: grep -o needle | wc -l
.
Com o Perl, aqui estão algumas maneiras que eu acho mais elegantes do que as suas (mesmo depois que ele é fixo ).
perl -lne 'END {print $c} map ++$c, /needle/g'
perl -lne 'END {print $c} $c += s/needle//g'
perl -lne 'END {print $c} ++$c while /needle/g'
Com apenas ferramentas POSIX, uma abordagem, se possível, é dividir a entrada em linhas com uma única correspondência antes de passá-la ao grep. Por exemplo, se você está procurando palavras inteiras, primeiro transforme cada caractere não pertencente à palavra em uma nova linha.
# equivalent to grep -ow 'needle' | wc -l
tr -c '[:alnum:]' '[\n*]' | grep -c '^needle$'
Caso contrário, não há um comando padrão para fazer esse processamento específico de texto, então você precisa ativar o sed (se você é masoquista) ou awk.
awk '{while (match($0, /set/)) {++c; $0=substr($0, RSTART+RLENGTH)}}
END {print c}'
sed -n -e 's/set/\n&\n/g' -e 's/^/\n/' -e 's/$/\n/' \
-e 's/\n[^\n]*\n/\n/g' -e 's/^\n//' -e 's/\n$//' \
-e '/./p' | wc -l
Aqui está uma solução mais simples usando sed
e grep
, que funciona para cadeias de caracteres ou até mesmo para expressões regulares, mas falha em alguns casos com padrões ancorados (por exemplo, encontra duas ocorrências de ^needle
ou \bneedle
em needleneedle
).
sed 's/needle/\n&\n/g' | grep -cx 'needle'
Observe que nas substituições do sed acima, usei \n
para significar uma nova linha. Isso é padrão na parte padrão, mas no texto de substituição, para portabilidade, substitua a barra invertida-newline por \n
.