read from stdin funciona de forma diferente em bash e zsh [duplicado]

0

Estou tentando canalizar a saída de um comando para o read interno de meu shell e obtenho um comportamento diferente para zsh e bash :

$ bash -c 'echo hello | read test; echo $test'

$ zsh -c 'echo hello | read test; echo $test'
hello

Embora isso não funcione em bash , o seguinte funciona para ambos:

 $ bash -c 'echo hello | while read test; do echo $test; done'
 hello
 $ zsh -c 'echo hello | while read test; do echo $test; done'
 hello

Por que isso? Estou usando read errado? Eu acho muito mais legível usá-lo em scripts em comparação com test="$(echo hello)" , o que me obriga a lidar com as questões de citação com muito mais cuidado.

    
por Doron Behar 21.10.2018 / 11:26

1 resposta

1

Você está observando os resultados do que não foi padronizado com o POSIX.

POSIX não padroniza como o interpretador executa um pipe.

Com a histórica Bourne Shell, o programa mais à direita em um pipeline não é nem mesmo uma criança da casca principal. A razão para fazer isso dessa maneira é porque essa implementação é lenta, mas precisa de poucos códigos - importante se você tiver apenas 64 kB de memória. Como nessa variante, o comando read é executado em um subprocesso, a designação de uma variável shell em um subprocesso não é visível no shell principal.

Os shells modernos como ksh ou bosh (o recente Bourne Shell) criam pipes de uma maneira em que todos os processos em um pipe são filhos diretos do shell principal e se o programa mais à direita é um shell embutido, é ainda executado pelo shell principal.

Tudo isso é necessário para permitir que o programa read modifique uma variável shell do shell principal. Portanto, somente nessa variante (que BTW é a variante mais rápida) permite que o shell principal veja os resultados da atribuição de variável.

Em seu segundo exemplo, todo o loop while é executado no mesmo subprocesso e, portanto, permite imprimir a versão modificada da variável shell.

Existe uma solicitação para adicionar suporte ao shell POSIX para obter informações sobre se algum dos comandos do pipeline tem um código de saída diferente de zero. Para conseguir isso, um shell deve ser implementado de forma que todos os programas de um pipeline sejam filhos diretos do shell principal. Isso está perto do que é necessário para permitir

echo foo | read val; echo $val

para fazer o que é esperado, desde então, apenas o requisito para executar a leitura no shell principal está faltando.

    
por 21.10.2018 / 11:36

Tags