Posso desativar o buffer para tr

6

tr parece armazenar em buffer sua entrada para que esse comando LongRunningCommand|tr \n , só comece a produzir saída depois que alguns kilobytes de entrada do LongRunningCommand tiverem sido acumulados.

Existe uma maneira de forçar tr a parar este buffer ou qualquer outro comando que possa substituir novas linhas por outro caracter sem buffer?

P.S. Já testei as duas primeiras sugestões de Desativar o buffer no tubo sem sucesso.

    
por ndemou 27.10.2015 / 16:02

2 respostas

8

Os comandos geralmente não armazenam suas entradas. Eles fariam um read() para um grande bloco, mas ao ler de um canal, se não houver muitos bytes no canal, a chamada do sistema read() retornará com quantos caracteres houver e o aplicativo geralmente trabalhe com isso se puder.

Uma exceção notável a isso é mawk , que continuará sendoread() até que o buffer de entrada esteja cheio.

Os aplicativos armazenam em buffer sua saída (stdout). O comportamento usual é que, se a saída estiver indo para um tty, o buffer será linear (isto é, ele não começará a gravar no stdout até que tenha uma linha completa para a saída ou um bloco cheio para long line), enquanto para qualquer outro tipo de arquivo, o buffer é por blocos (isto é, ele não vai começar a escrever até que tenha um bloco cheio para escrever (algo como 4KiB / 8KiB ... depende do software e do sistema) ).

Portanto, no seu caso, LongRunningCommand provavelmente armazena sua saída por blocos (já que sua saída é um canal e não um tty), e tr provavelmente armazena sua saída por linha, já que sua saída é provavelmente o terminal.

Mas, como você remove cada caractere de nova linha de sua saída, ele nunca exibirá uma linha, portanto, o armazenamento em buffer será por bloco.

Portanto, você deseja desativar o buffer para LongRunningCommand e tr . Nos sistemas GNU ou FreeBSD:

stdbuf -o0 LongRunningCommand | stdbuf -o0 tr '\n' ,

Observe que, se você deseja unir as linhas com uma vírgula, uma abordagem melhor é usar paste -sd , - . Dessa forma, a saída será terminada por um caractere de nova linha (você provavelmente ainda precisará desativar o buffer).

    
por 28.10.2015 / 16:18
5

Para substituir novas linhas por "," , você pode executar

awk '{ printf "%s,", $0 }'

O GNU awk ( gawk ) e o Solaris nawk serão executados com o buffer de linha no stdin e nenhum buffer de stdout quando a saída for para um terminal. Se o seu awk for mawk , o que acontece no Ubuntu, você pode dar a opção -W interactive para obter o mesmo comportamento de armazenamento em buffer.

    
por 28.10.2015 / 15:06

Tags