Diff stdin após piping através de um comando

6

Eu gostaria de algo na forma de (preencha os espaços em branco):

cmd1 | ____ cmd2 ____

Isso foi equivalente a isso, mas sem gravar nenhum arquivo:

cmd1 > temp
cmd2 < temp | diff temp -

cmd1 não é realmente um comando, é um fluxo de stdin de um editor de texto, por isso não pode ser executado mais de uma vez, então isso não funcionará:

diff <(cmd1) <(cmd1 | cmd2)

Mas isso é essencialmente o que eu quero.

Estou usando o macOS, mas também prefiro o linux.

    
por Aaron Jensen 13.01.2017 / 06:04

1 resposta

4

Geralmente, quando você não deseja gravar um arquivo, você pode substituí-lo por um pipe (nomeado), mas um pipe não pode ser lido por dois processos simultaneamente. No seu caso, você pode usar tee para dividir sua entrada e usar um canal nomeado para uma das suas extremidades:

mkfifo p
cmd1 | tee p | cmd2 | diff p -
rm p

Isso, no entanto, tem uma grande desvantagem: os pipes têm um buffer limitado (64k no Linux), então quando diff ler um deles excessivamente comparado com o outro, o pipeline inteiro estará em deadlock. O problema pode ser contornado usando o comando buffer para pelo menos um canal:

mkfifo p
cmd1 | tee p | cmd2 | buffer | diff p -
rm p

Veja também aqui para outros opções de buffering.

Outra solução para deadlocks é usar uma variável para armazenar em buffer a saída cmd1 inteira (carregando-a na memória):

cmd1 | ( b=$(cat); cmd2 <<<"$b" | diff <(echo "$b") - )
    
por 13.01.2017 / 11:16

Tags