Por que esse “while read” funciona em um terminal, mas não em um shell script?

6

Encontrei esse problema interessante ao preencher minha barra do WM com o texto da informação, que é aplicado definindo o título da janela raiz, ou seja, xsetroot -name "clever words"

Para isso, imprimir uma fortuna funciona bem em um terminal:

fortune -s | while read -r; do xsetroot -name "$REPLY"; done

No entanto, o mesmo falha quando executado a partir de um script de shell:

#!/bin/sh
cat /tmp/afile | while read; do echo "$REPLY"; done

Produz:

$ sh afilereader
afilereader: 2: read: arg count

É claro que isso é remediado atribuindo nosso resultado de fortuna a uma variável e, em seguida, usando xsetroot com a dita variável. Mas eu ainda gostaria de entender porque isso não funciona em um script.

Eu percebo que cada comando em cada lado do pipeline é executado dentro de seu próprio subshell, mas não consegue ver como suas variáveis localizadas podem afetar o loop while read. Ou as variáveis estão fora do escopo, mesmo entre as iterações do loop?

O que estou perdendo?

Atualização: O sh que usei está vinculado ao traço, que está em processo de se tornar compatível com POSIX. Usando o mais venerável bash resolveu isso.

    
por invert 12.11.2012 / 19:16

2 respostas

10

Você parece estar executando o primeiro exemplo em bash e o segundo em qualquer que seja apontado por /bin/sh , que é um shell POSIX que requer um argumento a ser passado especificando a variável na qual você deseja colocar a entrada . Alterar o shebang para #!/bin/bash deve corrigir isso.

    
por 12.11.2012 / 19:21
4

Na sintaxe sh, você precisa

IFS= read -r REPLY

Alguns shells como ksh, bash e zsh permitem que read seja chamado sem um nome de variável, mas o comportamento difere entre eles. Veja por exemplo a saída de

printf 'te\ st\\na ' | "$shell" -c 'read; printf "%s\n" "<$REPLY>"'

diferente em todos os bash, zsh, pdksh e ksh93

    
por 12.11.2012 / 20:15