: 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>&1
O Bash built-in
exec
pode 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 exec
no 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>&3
redireciona o fluxo do comando 1 (STDOUT) para o fluxo personalizado 3.2>&1
redireciona 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$exitcode
novamente. Você pode pesquisar mais informações sobre isso emman bash
, mas isso pode demorar um pouco ... -
exec 3>&-
O Bash built-in
exec
pode 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 exec
no 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 $exitcode
Este simples comando
echo
(mais informações sobreman echo
) apenas imprime o conteúdo das duas variáveis de Bashresult
eexitcode
para 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.