Não é tanto que não haja saída, pois está chegando em blocos.
Como muitos programas, quando sua saída não é mais um terminal, cut
armazena em buffer sua saída. Ou seja, ele grava apenas dados quando acumulou um buffer cheio dele. Normalmente, algo como 4 ou 8 kiB, embora YMMV.
Você pode verificar isso facilmente comparando:
(echo foo; sleep 1; echo bar) | cut -c2-
Com:
(echo foo; sleep 1; echo bar) | cut -c2- | cat
No primeiro caso, cut
ouputs oo\n
e ar\n
um segundo depois, enquanto no segundo caso, corte as saídas oo\nar\n
após 1 segundo, ou seja, quando ele vê o final de sua entrada e libera sua saída ao sair.
No seu caso, como stdin é nc
, ele só veria o final de sua entrada quando a conexão é fechada, portanto, ele só iniciaria a saída de qualquer coisa depois de acumular 4kiB de dados para gravar.
Para contornar isso, várias abordagens são possíveis.
-
Em sistemas GNU ou FreeBSD, você pode usar o utilitário
stdbuf
que pode ajustar o comportamento de buffer de alguns comandos (ele não funciona para todos, pois usa um hack LD_PRELOAD para pré-configurar o comportamento do stdio buffering).... | stdbuf -oL cut -d, -f15,16 | cat
diria
cut
para fazer um buffer baseado em linha em seu stdout. -
alguns comandos como o GNU
grep
possuem opções para afetar o buffer. (--line-buffered
no caso do GNUgrep
). -
você pode usar um empacotador pseudo-tty para forçar o stdout de um comando a ser um terminal. No entanto, a maioria dessas soluções tem algumas desvantagens e limitações. O script
unbuffer
expect
, por exemplo, frequentemente mencionado para resolver esse tipo de problema, possui vários bugs, por exemplo.Um que não funciona é quando usamos
socat
como:... | socat -u 'exec:"cut -d, -f15,16",pty,raw' -
-
Você pode substituir seu utilitário de texto por uma ferramenta de processamento de texto de alto nível que ofereça suporte a saída sem buffer.
-
O GNU
awk
por exemplo tem uma funçãofflush()
para liberar sua saída. Então, seucut -d, -f15,16
poderia ser escrito:awk -F, -vOFS=, '{print $15,$16;fflush()}'
-
se o seu
awk
não tiver a funçãofflush()
, você poderá usarsystem("")
. Normalmente é o comando para executar um comando. Aqui, estaríamos executando um comando vazio, mas realmente usando-o para o fato de queawk
libera seu stdout antes de executar o comando. -
ou você pode usar
perl
:perl -F, -lane 'BEGIN{$,=",";$|=1} print @F[14..15]'
-