Script que gera o número total de linhas em todos os arquivos de texto que são passados como argumentos

4

Estou trabalhando em um script que aceita argumentos que são arquivos de texto e deve gerar o número total de linhas nesses arquivos. Por exemplo, se eu disser

./myScript file1 file2 file3

imprimirá

10 total

(vamos supor que a soma de todas as linhas desses três arquivos seja 10).

Eu sei como repassar todos os argumentos. Eu também sei que, para obter o número de linhas em um arquivo, eu diria:

wc -l < fileName

No entanto, como posso fazer isso em um "int" que eu possa adicionar a algum tipo de soma cumulativa?

    
por Haz 20.09.2015 / 06:10

3 respostas

3

Você pode realizar seu objetivo simplesmente usando cat e um pipeline:

cat "$@" | wc -l

Se você realmente quisesse somar manualmente, você pode fazer isso com o awk:

for f in "$@"; do 
    wc -l < "$f"
done | awk '{ sum+=$1 } END { print sum }'

Ou se você realmente quisesse analisar a última linha de wc , removendo a string "total":

wc -l "$@" | awk 'END { print $1 }'
    
por 20.09.2015 / 06:18
2

Com base na resposta do jordanm:

1. Canalize todos os dados por meio de uma única instância de wc -l

if [ "$#" -gt 0 ]
then
    cat -- "$@" | wc -l
else
    echo 0
fi
ou%
cat -- /dev/null "$@" | wc -l
  • Use -- "$@" para proteger contra nomes de arquivos que começam com - .
  • Evite invocar cat sem argumentos como isso fará com que leia a entrada padrão.
  • Observe que cat a_single_file | something é a forma clássica do temido Uso inútil do gato , mas cat one_or_more_file(s) | something pode ser OK (embora ainda não seja o ideal).

2. Confie no fato de que wc emite uma linha “total”

if [ "$#" -gt 0 ]
then
    wc -l -- /dev/null "$@" | tail -1
else
    echo 0 total
fi
ou%
wc -l -- /dev/null /dev/null "$@" | tail -1
  • Observe que wc emite uma linha total somente se tiver pelo menos dois argumentos de nome de arquivo.

3. Use awk sem usar wc

if [ "$#" -gt 0 ]
then
    awk 'END {print NR}' -- "$@"
else
    echo 0
fi
ou%
awk 'END {print NR}' -- /dev/null "$@"

Aviso:

Os comandos acima não produzirão todos a mesma resposta se algum dos arquivos terminar com um caractere diferente de nova linha.

    
por 20.09.2015 / 08:36
1
sed -ne\$= files...

Apenas dê sed do número de arquivos que desejar em vez de files... e, depois de ler todos eles, ele informará o = número-da-linha do próprio $ última em sua entrada.

    
por 20.09.2015 / 19:20