grep -c
é útil para descobrir quantas vezes uma string ocorre em um arquivo, mas conta apenas cada ocorrência uma vez por linha. Como contar várias ocorrências por linha?
Estou procurando algo mais elegante do que:
perl -e '$_ = <>; print scalar ( () = m/needle/g ), "\n"'
grep
é especificado, mas para quem usaack
, a resposta é simplesack -ch <pattern>
.Respostas:
o grep's
-o
produzirá apenas as correspondências, ignorando as linhas;wc
pode contá-los:Isso também corresponderá a 'agulhas' ou 'multicamada'.
Apenas palavras simples:
fonte
\b
e\B
faz aqui?uniq
remove apenas as linhas idênticas adjacentes,sort
antes de alimentar,uniq
se ainda não tiver certeza de que as duplicatas sempre serão imediatamente adjacentes.Se você tiver GNU grep (sempre em Linux e Cygwin, ocasionalmente, em outros lugares), você pode contar as linhas de saída
grep -o
:grep -o needle | wc -l
.Com o Perl, aqui estão algumas maneiras que considero mais elegantes que as suas (mesmo depois de consertadas ).
Com apenas ferramentas POSIX, uma abordagem, se possível, é dividir a entrada em linhas com uma única correspondência antes de passá-la para grep. Por exemplo, se você estiver procurando por palavras inteiras, primeiro transforme todos os caracteres que não sejam palavras em uma nova linha.
Caso contrário, não há um comando padrão para fazer esse processamento específico de texto, então você precisa recorrer ao sed (se você é masoquista) ou awk.
Aqui está uma solução mais simples usando
sed
andgrep
, que funciona para strings ou mesmo expressões regulares, mas falha em alguns casos de canto com padrões ancorados (por exemplo, encontra duas ocorrências de^needle
ou\bneedle
emneedleneedle
).Observe que nas substituições sed acima, eu costumava
\n
significar uma nova linha. Isso é padrão na parte do padrão, mas no texto de substituição, para portabilidade, substitua a barra invertida-nova linha por\n
.fonte
Se, como eu, você realmente queria
"ambos; cada um exatamente uma vez"((na verdade, é "qualquer um; duas vezes"), então é simples:e verifique a saída
2
.O benefício dessa abordagem (se exatamente uma vez é o que você deseja) é que ela pode ser dimensionada facilmente.
fonte
Outra solução usando awk e
needle
como separador de campo:Se você deseja corresponder
needle
seguido de pontuação, altere o separador de campos de acordo.Ou use a classe:
[^[:alnum:]]
para abranger todos os caracteres não alfa.fonte
Seu exemplo imprime apenas o número de ocorrências por linha, e não o total no arquivo. Se é isso que você deseja, algo como isso pode funcionar:
fonte
Esta é a minha solução pura para o bash
fonte