AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 495324
Accepted
JoL
JoL
Asked: 2019-01-19 09:42:31 +0800 CST2019-01-19 09:42:31 +0800 CST 2019-01-19 09:42:31 +0800 CST

Por que `... | sed 's/^/stdout: /'` imprime em stdin vazio quando `... > >(sed 's/^/stdout: /')` não?

  • 772

Estou tentando entender o que causa a diferença nessas 2 construções que pensei serem funcionalmente equivalentes:

$ ( echo foo >&2 ) 2> >(sed 's/^/stderr: /') | sed 's/^/stdout: /'   
stdout: stderr: foo
$ ( echo foo >&2 ) 2> >(sed 's/^/stderr: /') > >(sed 's/^/stdout: /')
stderr: foo

EDIT: Se eu entendi user1133275 direito, ele sugere que >(sed 's/^/stdout: /')não seja executado, a menos que o subshell seja enviado ( echo foo >&2 )para stdout. No entanto, isso significaria que o seguinte:

$ ( echo foo >&2 ) 2> >(sed 's/^/stderr: /') > >(echo baz)   
baz
stderr: foo

não deve exibir baz.

EDIT 2: Talvez também de interesse, o sed não produz stdout:na entrada vazia, mesmo quando canalizado:

$ sed 's/^/stdout: /' < /dev/null
$ printf "" | sed 's/^/stdout: /'
$
bash sed
  • 4 4 respostas
  • 1857 Views

4 respostas

  • Voted
  1. Best Answer
    Kusalananda
    2019-01-19T10:23:41+08:002019-01-19T10:23:41+08:00

    Seu primeiro comando,

    ( echo foo >&2 ) 2> >(sed 's/^/stderr: /') | sed 's/^/stdout: /'
    

    de forma simplificada (usando um arquivo temporário para armazenar os dados produzidos por echo):

    { echo foo 2>file >&2; sed 's/^/stderr: /' file; } | sed 's/^/stdout: /'
    

    Ou seja, o primeiro sedlê o que é produzido no erro padrão do echoe grava na saída padrão e o segundo sedlê e modifica isso.

    Seu segundo comando,

    ( echo foo >&2 ) 2> >(sed 's/^/stderr: /') > >(sed 's/^/stdout: /')
    

    de forma simplificada,

    echo foo 2>file >&2; sed 's/^/stderr: /' file; sed 's/^/stdout: /' </dev/null
    

    Aqui, o sedque obtém a saída de erro padrão produz saída, enquanto o outro sedque obtém a saída de saída padrão (que não é nada) não produz nenhuma saída (já que não obteve nenhuma entrada e não inseriu ou anexou nenhum dado) .

    Outra forma de formular:

    Primeiro comando:

    ( echo foo >&2 ) 2>file
    sed 's/^/stderr: /' file | sed 's/^/stdout: /'
    

    Segundo comando:

    ( echo foo >&2 ) 2>file >otherfile
    sed 's/^/stderr: /' file
    sed 's/^/stdout: /' otherfile
    

    Em suma, o segundo sedno segundo comando nunca lê nada. Em particular, ele não lê a saída do primeiro sedcomo no primeiro comando.


    Usando símbolos extremamente simplificados, o primeiro comando é algo como

    utility-writing-to-stderr 2> >(something1) | something2
    

    onde something1grava na saída padrão, que é lida por something2.

    O segundo comando, usando a mesma notação,

    utility-writing-to-stderr 2> >(something1) >(something2)
    

    ou seja something1, e something2nem mesmo está conectado entre si, e something2não pode de forma alguma ler o que something1está produzindo. Além disso, como utility-writing-to-stderrnão produz nada em seu fluxo de saída padrão, something2não terá nada para ler de sua entrada padrão.

    • 3
  2. user1133275
    2019-01-19T09:52:04+08:002019-01-19T09:52:04+08:00

    >está operando ( echo foo >&2 )e |está operando por >(sed 's/^/stderr: /')causa da ordem de redirecionamento nos shells. POR EXEMPLO

    $ ( echo foo >&2 ) 2> >(sed 's/^/stderr: /' > >(sed 's/^/stdout: /') )
    stdout: stderr: foo
    

    ou

    $ ( echo foo >&2 ) 2> >(sed 's/^/stderr: /') | cat > >(sed 's/^/stdout: /')
    stdout: stderr: foo
    

    vs exemplos explícitos a ordem na pergunta

    $ ( ( echo foo >&2 ) > >(sed 's/^/stdout: /') ) 2> >(sed 's/^/stderr: /')
    stderr: foo
    

    ou

    $ ( ( echo foo >&2 )  | sed 's/^/stdout: /' ) 2> >(sed 's/^/stderr: /')
    stderr: foo
    
    • 1
  3. user232326
    2019-01-19T13:55:20+08:002019-01-19T13:55:20+08:00

    Os dois comandos não são equivalentes.

    O comando (1):

    ( one ) 2> >(two) | three 
    

    Envia a saída (std) de twopara three(Mais sobre stderr abaixo).

    O comando (2):

    ( one ) 2> >(two) > >(three)
    

    Envia a saída (std) de onepara three(stderr vai para two).


    O detalhe doloroso é:

    Comando 1:( one ) 2> >(two) | three

    • O comando threeé iniciado ( sed 's/^/stdout: /') aguardando entrada em stdin.
    • O redirecionamento de 2( stderr) para o stdinde twoocorre.
    • O redirecionamento interno de oneocorre ( echo foo >&2).
    • O comando é executado enviando foopara stderr(nada para stdout).
    • A palavra fooé redirecionada de ( stderrde one) para ( stdinde two).
    • O comando em dois é executado ( sed 's/^/stderr: /')
    • A saída agora modificada de two( stderr: foo) é enviada para o stdout de two.
    • O stdout atual de twopassa pelo pipe para three.
    • O comando threeque estava aguardando entrada desde o início obtém a saída.
    • A saída é modificada adicionando um stdout:.
    • A string final stdout: stderr: foovai para tty.

    Comando 2: (um) 2> >(dois) > >(três)

    • O último redirecionamento ( >) é construído primeiro.
    • O comando threeé iniciado aguardando entrada stdin somente em ( >()).
    • O comando threeobtém apenas o stdout de one.
    • O comando twoé iniciado aguardando entrada.
    • O comando twoobtém ( somente ) o stderr de one.
    • O redirecionamento interno de um conecta o stdout de oneao seu stderr.
    • O comando oneé executado enviando foopara o stderr(de one).
    • foovai paratwo
    • twoaltera a string recebida para stderr: fooe a envia para tty .
    • threerecebe uma entrada vazia do stdout de one.
    • threenão imprime nada (já que não há linha para processar).

    Entenda que este comando:

    printf '' | sed 's/^/initial: /'
    

    não tem saída (e não há como fazê-lo funcionar).


    Mudando a ordem: Comando 3: (um) > >(três) 2> >(dois)

    Faz com que a saída do detalhe twová para three(não o ) fique como um exercício.tty

    • 1
  4. Cbhihe
    2019-01-20T11:18:08+08:002019-01-20T11:18:08+08:00

    Eu votei na resposta muito clara de @Kusalananda, mas me arrisco a (tardiamente) adicionar isso à sua resposta, como uma pequena ilustração da substituição do processo em funcionamento:

    Sua segunda proposição funcionaria com uma pequena mudança tipográfica (e uma mudança comparativamente grande em sua lógica defeituosa):

      $ ( echo foo >&2 ) 2> >(sed 's/^/stderr: /') > >(sed 's/^/stdout: /')
      stderr: foo    # for the well explained reason above
    

    Mas:

        v                                          vv
      $ ( (echo foo >&2) 2> >(sed 's/^/stderr: /') )> >(sed 's/^/stdout: /')  
      stdout: stderr: foo
    

    Porque adicionar ( )>conforme ilustrado (ou >( ), ambos funcionam bem) na verdade permite que você crie um arquivo por meio de substituição de processo, cuja saída pode ser redirecionada como entrada para >(sed 's/^/stdout: /').

    Pensei em adicionar isso para ilustrar como a substituição de processo pode ser incorporada em outra substituição de processo. Para facilitar a leitura, eu não o empurraria para mais níveis de incorporação. Mas se por algum motivo você precisar evitar um pipe e o shell associado , esta é uma boa solução.

    • 0

relate perguntas

  • exportar variáveis ​​​​env programaticamente, via stdout do comando [duplicado]

  • Problema estranho ao passar variáveis ​​do arquivo de texto

  • Enquanto a linha lê mantendo os espaços de escape?

  • ordem de substituição de processos `te` e `bash`

  • Execute um script muito lento até que seja bem-sucedido

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve