Piping STDERR vs. STDOUT

21

De acordo com " Linux: A referência completa 6ª edição " (pág. 44), você pode canalizar somente STDERR usando os símbolos de redirecionamento |& .

Eu escrevi um script bem simples para testar isso:

#!/bin/bash
echo "Normal Text."
echo "Error Text." >&2

Eu corro este script assim:

./script.sh |& sed 's:^:\t:'

Presumivelmente, apenas as linhas impressas em STDERR serão recuadas. No entanto, não funciona assim, como eu vejo:

    Normal Text.
    Error Text. 

O que estou fazendo errado aqui?

    
por Naftuli Kay 11.11.2011 / 00:21

3 respostas

23

Eu não sei qual texto seu livro usa, mas o manual do bash está claro (se você já conhece um pouco os redirecionamentos):

If |& is used, command1’s standard error, in addition to its standard output, is connected to command2’s standard input through the pipe; it is shorthand for 2>&1 |. This implicit redirection of the standard error to the standard output is performed after any redirections specified by the command.

Portanto, se você não quiser misturar a saída padrão e o erro padrão, será necessário redirecionar a saída padrão para outro local. Veja Como grep stream de erro padrão (stderr)?

{ ./script.sh 2>&1 >&3 | sed 's:^:\t:'; } 3>&1

No entanto, os dois fd 1 e 3 de script.sh e sed apontarão para o destino stdout original. Se você quer ser um bom cidadão, pode fechar aqueles fd 3 que esses comandos não precisam:

{ ./script.sh 2>&1 >&3 3>&- | sed 's:^:\t:' 3>&-; } 3>&1

bash e ksh93 podem condensar o >&3 3>&- para >&3- (fd move).

    
por 11.11.2011 / 00:34
6

|& canaliza stderr para stdin, como 2>&1 | , então o próximo programa terá ambos em stdin.

$cat test.sh
#!/bin/bash
echo "Normal Text."
echo "Error Text." >&2
$./test.sh | sed 's:^:\t:'
Error Text.
        Normal Text.
$ ./test.sh |& sed 's:^:\t:'
        Normal Text.
        Error Text.
    
por 11.11.2011 / 00:33
1

|& no bash é apenas um atalho (não terrivelmente portátil) para 2>&1 | , então você deve ver cada linha recuada.

    
por 11.11.2011 / 00:31