J'ai peut-être quelque chose d'absolument erroné, mais cela me semble convaincant, que le fait de définir IFS comme l'une des commandes de la liste pre-do / done n'a absolument aucun effet.
L'IFS externe (en dehors de la while
construction) prévaut dans tous les exemples illustrés dans le script ci-dessous.
Que se passe t-il ici? Ai-je une mauvaise idée de ce que fait IFS dans cette situation? Je m'attendais à ce que les résultats du tableau soient divisés comme indiqué dans la colonne "attendu".
#!/bin/bash
xifs() { echo -n "$(echo -n "$IFS" | xxd -p)"; } # allow for null $IFS
show() { x=($1)
echo -ne " (${#x[@]})\t |"
for ((j=0;j<${#x[@]};j++)); do
echo -n "${x[j]}|"
done
echo -ne "\t"
xifs "$IFS"; echo
}
data="a b c"
echo -e "----- -- -- \t --------\tactual"
echo -e "outside \t IFS \tinside"
echo -e "loop \t Field \tloop"
echo -e "IFS NR NF \t Split \tIFS (actual)"
echo -e "----- -- -- \t --------\t-----"
IFS=$' \t\n'; xifs "$IFS"; echo "$data" | while read; do echo -ne '\t 1'; show "$REPLY"; done
IFS=$' \t\n'; xifs "$IFS"; echo "$data" | while IFS= read; do echo -ne '\t 2'; show "$REPLY"; done
IFS=$' \t\n'; xifs "$IFS"; echo "$data" | while IFS=b read; do echo -ne '\t 3'; show "$REPLY"; done
IFS=" "; xifs "$IFS"; echo "$data" | while read; do echo -ne '\t 4'; show "$REPLY"; done
IFS=" "; xifs "$IFS"; echo "$data" | while IFS= read; do echo -ne '\t 5'; show "$REPLY"; done
IFS=" "; xifs "$IFS"; echo "$data" | while IFS=b read; do echo -ne '\t 6'; show "$REPLY"; done
IFS=; xifs "$IFS"; echo "$data" | while read; do echo -ne '\t 7'; show "$REPLY"; done
IFS=; xifs "$IFS"; echo "$data" | while IFS=" " read; do echo -ne '\t 8'; show "$REPLY"; done
IFS=; xifs "$IFS"; echo "$data" | while IFS=b read; do echo -ne '\t 9'; show "$REPLY"; done
IFS=b; xifs "$IFS"; echo "$data" | while IFS= read; do echo -ne '\t10'; show "$REPLY"; done
IFS=b; xifs "$IFS"; echo "$data" | while IFS=" " read; do echo -ne '\t11'; show "$REPLY"; done
echo -e "----- -- -- \t --------\t-----"
Production:
----- -- -- -------- actual
outside IFS inside assigned
loop Field loop # inner
IFS NR NF Split IFS # expected IFS
----- -- -- -------- ----- # --------- --------
20090a 1 (3) |a|b|c| 20090a #
20090a 2 (3) |a|b|c| 20090a # |a b c| IFS=
20090a 3 (3) |a|b|c| 20090a # |a | c| IFS=b
20 4 (3) |a|b|c| 20 #
20 5 (3) |a|b|c| 20 # |a b c IFS=
20 6 (3) |a|b|c| 20 # |a | c| IFS=b
7 (1) |a b c| #
8 (1) |a b c| # |a|b|c| IFS=" "
9 (1) |a b c| # |a | c| IFS=b
62 10 (2) |a | c| 62 # |a b c| IFS=
62 11 (2) |a | c| 62 # |a|b|c| IFS=" "
----- -- -- -------- ----- --------- -------
$IFS
sont supprimés au début / à la fin de la ligne d'entrée, je suppose? (C'est ainsi que cela fonctionne.)a<tab>b
enread var
se traduira par var ayant la valeura<space>b
, mais si au contraire , vous avezIFS='<newline>' read var
alors la valeur de var seraa<tab>b
.En termes simples, vous devez lire plusieurs variables à la fois pour que la
IFS=<something> read ...
construction ait un effet visible dans vos exemples 1 .Vous manquez la portée de
read
dans les exemples. Il n'y a aucune modification d'IFS à l'intérieur de la boucle dans vos cas de test. Permettez-moi de vous indiquer exactement où le deuxième IFS a son effet dans chacune de vos lignes:C'est comme pour tout programme exécuté dans le shell. La variable que vous (re) définissez sur la ligne de commande affecte l'exécution du programme. Et seulement cela (puisque vous n'exportez pas). Par conséquent, pour faire un usage de redéfini
IFS
dans une telle ligne, vous devez demanderread
d'attribuer des valeurs à plusieurs variables . Jetez un œil à ces exemples:1 Comme je viens de l'apprendre de Gilles , il pourrait en fait être avantageux de définir
IFS=''
(vide) lors de la lecture d'un seul champ: cela évite la troncature des espaces au début de la ligne.la source
IFS= read
utilisé de préférence à simplement réinitialiser la variable d'environnement IFS". Je ne savais pas, alors, que les variables locales pouvaient être définies par l'appelant d'une commande. C'était la réponse à cette question. Il a évolué davantage pour aborder le point principal de cette question, mais au moment où je me suis rendu compte que j'avais déjà posé cette question ... Peut-être que les deux questions sont aussi similaires que deuxsed
questions, donc j'ai l'impression de le garder tel quel ... Plus de titres pour les googleurs sur google.