$ awk '/Bond/{c++; print "There is a match on line " NR} END{print "\"Bond\" appeared " c " times in the file " FILENAME}' bond.txt
There is a match on line 1
There is a match on line 8
"Bond" appeared 2 times in the file bond.txt
Como funciona
O awk implicitamente percorre todas as linhas de entrada.
-
/Bond/{c++; print "There is a match on line " NR}
Para linhas que correspondem à regex
Bond
, o contadorc
é incrementado e uma mensagem é impressa mostrando em qual linha a correspondência está ativada. No awk, o número de linhas lidas até agora éNR
. -
END{print "\"Bond\" appeared " c " times in the file " FILENAME}
Após a última linha ser lida, uma mensagem é impressa mostrando o número total de correspondências.
Versão de várias linhas
Para quem gosta do código espalhado por várias linhas:
awk '
/Bond/{
c++
print "There is a match on line " NR
}
END{
print "\"Bond\" appeared " c " times in the file " FILENAME
}
' bond.txt
Exibindo o conteúdo do arquivo antes do resumo do arquivo
Esta abordagem lê o arquivo duas vezes. Na primeira vez, imprime a versão do arquivo formatado com números de linha. A segunda vez que imprime a saída de resumo:
$ awk 'FNR==NR{printf("%5d) %s\n", NR,$0);next} /Bond/{c++; print "There is a match on line " FNR} END{print "\"Bond\" appeared " c " times in the file " FILENAME}' bond.txt{,}
1) Secret agent Bond had been warned not to tangle with Goldfinger.
2) But the super-criminal's latest obsession was too strong, too dangerous.
3) He had to be stopped.
4) Goldfinger was determined to take possession of half the supply of
5) mined gold in the world--to rob Fort Knox!
6) For this incredible venture he had enlisted the aid of the top
7) criminals in the U.S.A, including a bevy of beautiful thieves from the
8) Bronx. And it would take all of Bond's unique talents to make it fail--
9) as fail it must.
There is a match on line 1
There is a match on line 8
"Bond" appeared 2 times in the file bond.txt
O acima difere da primeira versão de duas maneiras. Primeiro, o arquivo é fornecido na linha de comando duas vezes como bond.txt bond.txt
ou, usando um truque de expansão de chave brace , como bond.txt{,}
.
Em segundo lugar, adicionamos o comando:
FNR==NR{printf("%5d) %s\n", NR,$0);next}
Este comando só é executado se FNR==NR
onde NR é o total do número de linhas lidas até agora e FNR é o número de linhas lidas do arquivo atual. Então, quando FNR==NR
, estamos lendo o arquivo pela primeira vez. Em seguida, printf
da saída formatada e pula para a linha next
, ignorando o restante dos comandos no script.
Alternativa
Nesta versão, lemos o arquivo apenas uma vez, imprimindo a versão formatada enquanto salvamos as informações de resumo a serem impressas no final:
$ awk '{printf("%5d) %s\n", NR,$0)} /Bond/{c++; s=s ORS "There is a match on line " FNR} END{print s; print "\"Bond\" appeared " c " times in the file " FILENAME}' bond.txt
1) Secret agent Bond had been warned not to tangle with Goldfinger.
2) But the super-criminal's latest obsession was too strong, too dangerous.
3) He had to be stopped.
4) Goldfinger was determined to take possession of half the supply of
5) mined gold in the world--to rob Fort Knox!
6) For this incredible venture he had enlisted the aid of the top
7) criminals in the U.S.A, including a bevy of beautiful thieves from the
8) Bronx. And it would take all of Bond's unique talents to make it fail--
9) as fail it must.
There is a match on line 1
There is a match on line 8
"Bond" appeared 2 times in the file bond.txt