alterando IFS temporariamente antes de um loop for [duplicado]
Eu sei que o SHELL
permite 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; done
mas 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 for
loops.
Respostas
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 for
loop, 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
$PATH
passa 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 IFS
atribuição se aplica a read
, portanto, está tudo OK.