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
stdbufque 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 | catdiria
cutpara fazer um buffer baseado em linha em seu stdout. -
alguns comandos como o GNU
greppossuem opções para afetar o buffer. (--line-bufferedno 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
unbufferexpect, por exemplo, frequentemente mencionado para resolver esse tipo de problema, possui vários bugs, por exemplo.Um que não funciona é quando usamos
socatcomo:... | 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
awkpor exemplo tem uma funçãofflush()para liberar sua saída. Então, seucut -d, -f15,16poderia ser escrito:awk -F, -vOFS=, '{print $15,$16;fflush()}' -
se o seu
awknã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 queawklibera seu stdout antes de executar o comando. -
ou você pode usar
perl:perl -F, -lane 'BEGIN{$,=",";$|=1} print @F[14..15]'
-