designa o número de linhas de saída para uma variável

2

Como posso executar um comando a partir de um script bash e ao final imprimir o número de linhas que ele imprimiu?

O equivalente do awk seria

{ print; } 
END { print NR; }

Eu só poderia apresentar o seguinte. Isso funciona por enquanto, mas não consigo colocá-lo fora da sub-rede.

| (lc=0; while read; do echo $REPLY; lc=$(($lc+1)); done; echo $lc)

UPDATE

Parece que meu problema era algo bem diferente. Eu tentei usar /dev/stdout que falhou:

tester> { echo abc | tee /dev/stdout | wc -l;  } > /tmp/abc; cat /tmp/abc
2

Isso parece ser porque tee /dev/stdout dá erro:

tester> echo abc | tee /dev/stdout
tee: /dev/stdout: Permission denied
abc

A resposta de Jeff Schaller funcionou:

tester> { echo abc | tee >(wc -l);  } > /tmp/abc; cat /tmp/abc
abc
1

Mas esta manhã, ao tentar novamente, vi que funciona!

tmp> echo abc | tee /dev/stdout
abc
abc

Depois de passar algum tempo, encontrei dois problemas:

Quando |tee /dev/stdout falhou ontem eu tinha logado como usr1 feito um sudo para outro usr2, sudo su usr2 . Nesse caso, a cadeia do link flexível é /dev/stdout -> /proc/self/fd/1 -> /dev/pts/1 e a última, usr1 . Então, o tee falhou. Hoje eu tentei como usr1, então foi bem sucedido.

Mas percebi o outro erro com tee /dev/stdout , que é que toda a saída vai para wc -l ; A contagem de linhas é dupla e nada é impresso.

    
por Miserable Variable 17.05.2017 / 01:15

3 respostas

1

Não sei como a contagem de linhas poderia ser melhor:

$ seq 1 5 2>&1 | tee >(wc -l | { read lines; echo Lines of output: $lines; })
1
2
3
4
5
$ Lines of output: 5

Isso redireciona o stderr do comando (here seq 1 5 ) para stdout, para que tee veja ambos os fluxos; tee então copia sua entrada de volta e também copia a entrada para uma substituição de processo que executa wc -l para contar as linhas. Em seguida, leio a saída de wc na variável $lines para fornecer um relatório.

    
por 17.05.2017 / 03:47
2

Usando sed :

some_command | sed -n 'p;$='

Por exemplo:

$ touch file.{a..k}
$ printf '%s\n' * | sed -n 'p;$='
file.a
file.b
file.c
file.d
file.e
file.f
file.g
file.h
file.i
file.j
file.k
11

O script sed apenas copiará a entrada para a saída com o comando de impressão ( p ) aplicado a cada linha de entrada, mas para a última linha ( $ ), também imprimirá o número da linha ( = ).

    
por 17.05.2017 / 22:30
1

Você pode simplesmente usar o comando awk:

echo -e "foo\nbar"| awk '{ print; }END { print NR; }'
foo
bar
2
    
por 17.05.2017 / 12:08