alterando IFS temporariamente antes de um loop for [duplicado]

Aug 16 2020

Eu sei que o SHELLpermite que a atribuição de variáveis ​​ocorra imediatamente antes de um comando, de forma que IFS=":" read a b c d <<< "$here_string"funcione ...

O que eu queria saber é se essas atribuições não funcionam quando feitas com instruções compostas, como loops? Tentei algo parecido, IFS=":" for i in $PATH; do echo $i; donemas resultou em um erro de sintaxe. Eu sempre poderia fazer algo como oldIFS="$IFS"; IFS=":"; for....; IFS="$oldIFS", mas queria saber se havia alguma maneira de fazer essas atribuições inline funcionarem para instruções compostas como forloops.

Respostas

3 Quasímodo Aug 16 2020 at 21:12

foré uma palavra reservada e, como tal, segue regras especiais :

As seguintes palavras devem ser reconhecidas como palavras reservadas:

! {} case faça elif else esac fi para if in then até while

Este reconhecimento só ocorrerá quando nenhum dos caracteres for citado e quando a palavra for usada como:

  • A primeira palavra de um comando

  • A primeira palavra após uma das palavras reservadas diferente de case , for ou in

  • A terceira palavra em um comando de caso (somente em é válido neste caso)

  • A terceira palavra em um comando for (apenas in e do são válidos neste caso)

Se você tentar

IFS=":" for i in $PATH; do echo $i; done

, pelas regras acima, isso não é um forloop, pois a palavra-chave não é a primeira palavra do comando. Mas sua intenção pode ser alcançada com

IFS=: printf '%s\n' $PATH

$PATHpassa pela divisão de palavras :conforme o esperado e cada palavra resultante é impressa por printf, seguida por uma nova linha.


Você pode estar familiarizado com esta abordagem válida:

while IFS= read -r line; do

whileé a primeira palavra do comando e a IFSatribuição se aplica a read, portanto, está tudo OK.