En bash, dites que vous avez var=abc
, alors:
$ IFS=. printf "%s\n" $var abc
Cependant, une telle utilisation de l' IFS
prend effet lors de la création d'un tableau:
$ IFS=. arr=($var) $ printf "%s\n" "${arr[@]}" a b c
C'est très pratique, bien sûr, mais où est-ce documenté? Une lecture rapide des sections sur les arrays ou la division de mots dans la documentation Bash ne donne aucune indication d'une façon ou d'une autre. Une search d' IFS
travers la documentation d'une seule page ne fournit aucune indication sur cet effet non plus.
Je ne sais pas quand je peux faire de façon fiable:
IFS=x do something
Et attendez-vous à ce que l' IFS
affecte le fractionnement du champ.
L'idée de base est que VAR=VALUE some-command
met VAR
en VALUE
pour l'exécution de some-command
quand some-command
est une command externe, et il n'a pas plus de fantaisie que cela. Si vous combinez cette intuition avec une certaine connaissance du fonctionnement d'un shell, vous devriez find la bonne réponse dans la plupart des cas. La reference POSIX est "Commandes simples" dans le chapitre "Langage de command Shell" .
Si some-command
est une command externe , VAR=VALUE some-command
est équivalent à env VAR=VALUE some-command
. VAR
est exporté dans l'environnement d'une some-command
, et sa valeur (ou l'absence d'une valeur) dans le shell ne change pas.
Si some-command
est une fonction , alors VAR=VALUE some-command
est équivalente à VAR=VALUE; some-command
VAR=VALUE; some-command
, c'est VAR=VALUE; some-command
dire que l'affectation rest en place après le return de la fonction et que la variable n'est pas exscope dans l'environnement. La raison en est la design du shell Bourne (et par la suite avec compatibilité ascendante): il n'a pas été possible de sauvegarder et de restaurer des valeurs variables autour de l'exécution d'une fonction. L'export de la variable n'a pas de sens puisqu'une fonction s'exécute dans le shell lui-même. Cependant, ksh (y compris à la fois ATT ksh93 et pdksh / mksh), bash et zsh implémentent le comportement plus utile où VAR
est défini uniquement pendant l'exécution de la fonction (il est également exporté). En ksh , ceci est fait si la fonction est définie avec la function NAME …
syntaxe ksh function NAME …
, pas si elle est définie avec la syntaxe standard NAME ()
. En bash , cela se fait uniquement en mode bash, pas en mode POSIX (lorsqu'il est exécuté avec POSIXLY_CORRECT=1
). Dans zsh , ceci est fait si l'option posix_builtins
n'est pas définie; cette option n'est pas définie par défaut mais est activée par emulate sh
ou emulate ksh
.
Si some-command
est un builtin, le comportement dépend du type de builtin. Les builtins spéciaux se comportent comme des fonctions. Les built-ins spéciaux sont ceux qui doivent être implémentés à l'intérieur du shell car ils affectent le shell d'état (par exemple, break
affecte le stream de contrôle, cd
affecte le directory courant, set
affecte les parameters de position et les options …). Les autres architectures ne sont embeddedes que pour des raisons de performances et de commodité (la plupart du time, par exemple, la fonctionnalité bash printf -v
ne peut être implémentée que par un builtin) et elles se comportent comme une command externe.
L'affectation a lieu après l'expansion de l'alias, donc si some-command
est un alias , développez-la d'abord pour find ce qui se passe.
Notez que dans tous les cas, l'affectation est effectuée après l'parsing de la command line, y compris toute substitution de variable sur la command line elle-même. Donc var=a; var=b echo $var
var=a; var=b echo $var
affiche a
, car $var
est évalué avant que l'affectation n'ait lieu. Et donc IFS=. printf "%s\n" $var
IFS=. printf "%s\n" $var
utilise l'ancienne valeur IFS
pour split $var
.
J'ai couvert tous les types de commands, mais il y a un autre cas: quand il n'y a pas de command à exécuter , c'est-à-dire si la command consiste uniquement en assignations (et éventuellement en redirections). Dans ce cas, la mission rest en place . VAR=VALUE OTHERVAR=OTHERVALUE
est équivalent à VAR=VALUE; OTHERVAR=OTHERVALUE
VAR=VALUE; OTHERVAR=OTHERVALUE
. Donc après IFS=. arr=($var)
IFS=. arr=($var)
, IFS
rest défini sur .
. Puisque vous pouvez utiliser $IFS
dans l'assignation à arr
avec la prévision qu'elle a déjà sa nouvelle valeur, il est logique que la nouvelle valeur de IFS
soit utilisée pour l'extension de $var
.
En résumé, vous pouvez utiliser IFS
uniquement pour la division temporaire des champs:
third=$(IFS=.; set -f; set -- $var; echo "$3")
est une façon compliquée de faire un third=${var#*.*.}
sauf qu'ils se comportent différemment lorsque la valeur de var
contient less de deux caractères. IFS=. some-function
IFS=. some-function
où some-function
est défini avec la function some-function …
syntaxe ksh function some-function …
; IFS=. some-function
IFS=. some-function
tant qu'ils fonctionnent en mode natif par opposition au mode de compatibilité. La réponse de @Gilles est vraiment géniale, il explique (en détail) un problème complexe.
Cependant, je crois que la réponse à pourquoi cette command:
$ IFS=. printf "%s\n" $var abc
fonctionne comme il le fait est l'idée simple que toute la command line est analysée avant qu'il soit exécuté. Et que chaque "mot" est traité une fois par le shell.
Les affectations, comme IFS=.
, sont retardés (l'étape 4 est la dernière):
4.- Chaque assignation de variable doit être étendue …
jusqu'au moment où la command est exécutée et que toutes les expansions dans les arguments sont traitées en premier pour build cette ligne exécutable:
$ IFS=. printf "%s\n" abc ## IFS=. goes to the environment. abc
La valeur de $var
est étendue avec l'ancien IFS à abc
avant que la command printf
ne reçoive les arguments "%s\n"
et abc
.
Un niveau de retard peut être introduit par eval
:
$ IFS=. eval printf "'%s\n'" \$var a b c
La ligne est analysée (1ère fois) et "IFS =." est défini sur l'environnement comme ceci:
$ printf '%s\n' $var
Ensuite, il est analysé à nouveau:
$ printf '%s\n' abc
Et exécuté à ceci:
a b c
La valeur de $var
(abc) est divisée par la valeur de IFS utilisée:. .
La partie complexe et délicate est ce qui est valable dans l'environnement quand !!!
C'est très bien expliqué dans la première partie de Gilles.
Avec un détail supplémentaire.
Lorsque cette command est exécutée:
$ IFS=. arr=($var)
La valeur de l'IFS est conservée dans l'environnement actuel, oui:
$ printf '<%s> ' "${arr[@]}" "$IFS" <a> <b> <c> <.>
Mais cela pourrait être évité: Définir IFS pour une seule instruction
$ IFS=. command eval arr\=\(\$var\) $ printf '<%s> ' "${arr[@]}" "$IFS" <a> <b> <c> < >
Votre question concernant
var=abc IFS=. printf "%s\n" $var
est un cas de coin.
Cela est dû au fait que l' macro expansion
la macro expansion
dans la command se produit avant la variable shell IFS=.
est réglé.
En d'autres termes: lorsque $var
est développé, la valeur IFS
précédente est active, alors IFS
est défini sur '.'
.