: D Eu não posso explicar isso !!! Se você puder entender o que eles estão dizendo no Guia Avançado de Roteiro de Bash: Capítulo 20. Redirecionamento de I / O , escreva uma nova resposta e eu lhe darei 50rep :
exec 3>&1; result=$(dialog --inputbox test 0 0 2>&1 1>&3); exitcode=$?; exec 3>&-; echo $result $exitcode;Referência: O diálogo no bash é Não pegar variáveis corretamente
^ resposta de @Sneetsher (4 de julho de 2014)
Conforme solicitado, tentarei explicar o que este snippet está fazendo linha por linha.
Note que eu simplificarei isso omitindo todos os ; ponto e vírgula nas extremidades da linha, porque eles não são necessários se escrevermos um comando por linha.
E / S - fluxos:
Primeiro, você precisa entender os fluxos de comunicação. Existem 10 fluxos, numerados de 0 a 9:
-
Fluxo 0 ("STDIN"):
"Entrada padrão", o fluxo de entrada padrão para ler dados do teclado. -
Stream 1 ("STDOUT"):
"Saída padrão", o fluxo de saída padrão usado para mostrar texto normal no terminal. -
Fluxo 2 ("STDERR"): "Erro padrão", o fluxo de saída padrão usado para exibir erros ou outro texto para fins especiais no terminal.
-
Fluxos 3-9:
Fluxos adicionais, livremente utilizáveis. Eles não são usados por padrão e não existem até que algo tente usá-los.
Observe que todos os "fluxos" são representados internamente pelos descritores de arquivos em /dev/fd (que é um link simbólico para /proc/self/fd que contém outro link simbólico para cada fluxo ... é um pouco complicado e não é importante para o comportamento deles Então eu paro aqui. Os fluxos padrão também têm /dev/stdin , /dev/stdout e /dev/stderr (que são links simbólicos novamente, etc ...).
O script:
-
exec 3>&1O Bash built-in
execpode ser usado para aplicar um redirecionamento de fluxo ao shell, o que significa que ele afeta todos os comandos a seguir. Para mais informações, executehelp execno seu terminal.Neste caso especial, o fluxo 3 é redirecionado para o fluxo 1 (STDOUT), o que significa que tudo que enviamos para o fluxo 3 mais tarde aparecerá em nosso terminal como se fosse normalmente impresso em STDOUT.
-
result=$(dialog --inputbox test 0 0 2>&1 1>&3)Esta linha consiste em muitas partes e estruturas sintáticas:
-
result=$(...)
Essa estrutura executa o comando entre colchetes e atribui a saída (STDOUT) à variável bashresult. É legível através de$result. Tudo isso é descrito de alguma forma na veeeery looongman bash. -
dialog --inputbox TEXT HEIGHT WIDTH
Este comando mostra uma caixa de TUI com o TEXTO dado, um campo de entrada de texto e dois botões OK e CANCELAR. Se OK for selecionado, o comando sai com o status 0 e imprime o texto digitado em STDERR, se CANCEL for selecionado, sairá com o código 1 e não imprimirá nada. Para mais informações, leiaman dialog. -
2>&1 1>&3
Estes são dois comandos de redirecionamento. Eles serão interpretados da direita para a esquerda:1>&3redireciona o fluxo do comando 1 (STDOUT) para o fluxo personalizado 3.2>&1redireciona depois o fluxo do comando 2 (STDERR) para o fluxo 1 (STDOUT).Isso significa que tudo o que o comando imprime no STDOUT aparece agora no fluxo 3, enquanto tudo o que deveria ser exibido no STDERR agora é redirecionado para o STDOUT.
Assim, a linha inteira exibe um prompt de texto (no STDOUT, que foi redirecionado para o fluxo 3, que o shell redireciona novamente para STDOUT no final - veja o comando
exec 3>&1) e atribui os dados inseridos (retornados pelo STDERR , em seguida, redirecionado para STDOUT) para a variável de bashresult. -
-
exitcode=$?Este código recupera o código de saída do comando executado anteriormente (aqui de
dialog) através da variável reservada Bash$?(sempre mantém o último código de saída) e simplesmente o armazena em nossa própria variável Bashexitcode. Pode ser lido por$exitcodenovamente. Você pode pesquisar mais informações sobre isso emman bash, mas isso pode demorar um pouco ... -
exec 3>&-O Bash built-in
execpode ser usado para aplicar um redirecionamento de fluxo ao shell, o que significa que ele afeta todos os comandos a seguir. Para mais informações, executehelp execno seu terminal.Neste caso especial, o stream 3 é redirecionado para "stream -", o que significa que deve ser fechado. Os dados enviados para o stream 3 não serão redirecionados para mais lugar algum a partir de agora.
-
echo $result $exitcodeEste simples comando
echo(mais informações sobreman echo) apenas imprime o conteúdo das duas variáveis de Bashresulteexitcodepara o STDOUT. Como não temos mais nenhum redirecionamento de fluxo explícito ou implícito aqui, eles realmente aparecerão no STDOUT e, portanto, simplesmente serão exibidos no terminal. Que milagre!; -)
Resumo:
Primeiro, configuramos o shell para redirecionar tudo que enviamos para o fluxo customizado 3 de volta para STDOUT, para que ele apareça em nosso terminal.
Em seguida, executamos o comando dialog , redirecionamos seu STDOUT original para nosso fluxo personalizado 3, porque ele precisa ser exibido no final, mas precisamos usar temporariamente o fluxo STDOUT para outra finalidade.
Nós redirecionamos o STDERR original do comando, onde a entrada do usuário da janela de diálogo é retornada, para STDOUT depois.
Agora podemos capturar o STDOUT (que contém os dados redirecionados do STDERR) e armazená-lo em nossa variável $result . Ele contém a entrada do usuário desejada agora!
Também queremos o código de saída do comando dialog , que mostra se OK ou CANCEL foi clicado. Este valor é apresentado na variável Bash reservada $? e nós apenas copiamos para nossa variável $exitcode .
Depois disso, fechamos o stream 3 novamente, já que não precisamos mais dele, para impedir mais redirecionamentos dele.
Por fim, normalmente emitimos o conteúdo de ambas as variáveis $result (a entrada do usuário da janela de diálogo) e $exitcode (0 para OK, 1 para CANCEL) no terminal.