Para aqueles que querem contar todas instâncias, aqui está uma versão do awk que contará várias não-sobrepostas quando houver mais de um na mesma linha
UPDATE: Eu incluí agora outro método que usa split(...
. É muito mais rápido que o método match( substr(...
, que agora está listado abaixo do mais rápido.
O método split(...
é mais de 4 vezes mais rápido que o outro ... (testado em 87 arquivos para um total de 407.612 linhas).
Para uma comparação adicional, o método Michael Mrozek's , usando /Sync/
range-selection (que conta linhas contendo cada padrão vs. contando todas as instâncias do padrão) é duas vezes mais rápido que este novo método (para os mesmos dados).
Outro benefício de franja (?) deste mais rápido split(methos)
é que ele é bastante tolerante a caracteres UTF-8 inválidos no arquivo (contanto que eles não estejam no padrão delimitador) ... Os delimitadores são os próprios padrões de string reais sendo contados ... Vários dos meus arquivos de teste tinham UTF-8 inválido neles e levei um bom tempo para descobrir por que obtive resultados diferentes dos dois métodos.
Depois que os arquivos com problemas foram recodificados para validar o UTF-8, ambos os métodos produzem resultados idênticos.
Aqui está o novo método mais rápido (4+ vezes mais rápido) ... usando split(...
#!/bin/bash
pat='xx|yy|zz'
awk -v vpat="$pat" 'BEGIN {
split(vpat, pat, "|"); for(i in pat) pz++
}
{ if (NF) { for( p in pat ) { ct[p]+=(split( $0, A, pat[p] ) -1) }}
}
END { print " count pattern"
for (p=1; p<=pz; p++) { printf "%6d %s\n", +ct[p], pat[p] }
}' file
Aqui está o método mais lento. usando match( substr(...
#!/bin/bash
# Count occurrences of multiple non-overlapping string patterns
awk 'BEGIN {
pattern[1]="xx"
pattern[2]="yy"
pattern[3]="zz"
}
{ for( p in pattern ) {
LHB=0; RSTART=RLENGTH=1
while( match( substr( $0, LHB+=(RSTART+RLENGTH-1)), pattern[p] )){
count[p]++
}
}
} END {
print "occurs pattern"
for (p in pattern) {
printf "%6d %s\n", +count[p], pattern[p]
}
}' file
Aqui está o arquivo de entrada
xx xx xx
xx yy xx
A saída é a seguinte:
occurs pattern
5 xx
1 yy
0 zz