changement IFS temporairement avant une boucle for [duplicate]

Aug 16 2020

Je sais que le SHELLpermet l'attribution de variables à avoir lieu immédiatement avant une commande, de sorte que cela IFS=":" read a b c d <<< "$here_string"fonctionne ...

Ce que je me demandais, c'est que de telles affectations ne fonctionnent pas lorsqu'elles sont faites avec des instructions composées telles que des boucles? J'ai essayé quelque chose comme IFS=":" for i in $PATH; do echo $i; donemais cela entraîne une erreur de syntaxe. Je pourrais toujours faire quelque chose comme oldIFS="$IFS"; IFS=":"; for....; IFS="$oldIFS", mais je voulais savoir s'il y avait un moyen pour que de telles affectations en ligne fonctionnent pour des instructions composées comme des forboucles?

Réponses

3 Quasímodo Aug 16 2020 at 21:12

forest un mot réservé et en tant que tel suit des règles spéciales :

Les mots suivants sont reconnus comme des mots réservés:

! {} case do done elif else esac fi for if in then jusqu'à while

Cette reconnaissance ne doit avoir lieu que lorsqu'aucun des caractères n'est cité et que le mot est utilisé comme:

  • Le premier mot d'une commande

  • Le premier mot suivant l'un des mots réservés autres que case , for ou in

  • Le troisième mot dans une commande de cas (seulement dans est valide dans ce cas)

  • Le troisième mot d'une commande for (seuls les in et do sont valides dans ce cas)

Si tu essayes

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

, selon les règles ci-dessus, ce n'est pas une forboucle, car le mot-clé n'est pas le premier mot de la commande. Mais votre intention pourrait être atteinte avec

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

$PATHsubit le fractionnement de mot :comme prévu et chaque mot résultant est imprimé par printf, suivi d'une nouvelle ligne.


Vous connaissez peut-être cette approche valide:

while IFS= read -r line; do

whileest le premier mot de la commande, et l' IFSaffectation s'applique à read, donc tout va bien.