Dans les anciennes versions, bash
vous deviez citer des variables après <<<
. Cela a été corrigé dans 4.4. Dans les anciennes versions, la variable était divisée sur IFS et les mots résultants joints dans l'espace avant d'être stockés dans le fichier temporaire qui constitue cette <<<
redirection.
En 4.2 et avant, lors de la redirection de buildins comme read
ou command
, ce fractionnement prendrait même l'IFS pour ce builtin (4.3 corrigé cela):
$ bash-4.2 -c 'a=a.b.c.d; IFS=. read x <<< $a; echo "$x"'
a b c d
$ bash-4.2 -c 'a=a.b.c.d; IFS=. cat <<< $a'
a.b.c.d
$ bash-4.2 -c 'a=a.b.c.d; IFS=. command cat <<< $a'
a b c d
Celui-ci corrigé en 4.3:
$ bash-4.3 -c 'a=a.b.c.d; IFS=. read x <<< $a; echo "$x"'
a.b.c.d
Mais il $a
est toujours sujet à la division des mots:
$ bash-4.3 -c 'a=a.b.c.d; IFS=.; read x <<< $a; echo "$x"'
a b c d
En 4.4:
$ bash-4.4 -c 'a=a.b.c.d; IFS=.; read x <<< $a; echo "$x"'
a.b.c.d
Pour la portabilité vers les anciennes versions, citez votre variable (ou utilisez d' zsh
où cela <<<
vient en premier lieu et qui n'a pas ce problème)
$ bash-any-version -c 'a=a.b.c.d; IFS=.; read x <<< "$a"; echo "$x"'
a.b.c.d
Notez que cette approche pour diviser une chaîne ne fonctionne que pour les chaînes qui ne contiennent pas de caractères de nouvelle ligne. Notez également que a..b.c.
serait divisé en "a"
, ""
, "b"
, "c"
(pas vide dernier élément).
Pour diviser des chaînes arbitraires, vous pouvez utiliser l'opérateur split + glob à la place (ce qui le rendrait standard et éviterait de stocker le contenu d'une variable dans un fichier temporaire comme le <<<
fait):
var='a.new
line..b.c.'
set -o noglob # disable glob
IFS=.
set -- $var'' # split+glob
for i do
printf 'item: <%s>\n' "$i"
done
ou:
array=($var'') # in shells with array support
Il ''
s'agit de conserver un élément vide de fin le cas échéant. Cela diviserait également un vide $var
en un élément vide.
Ou utilisez un shell avec un opérateur de fractionnement approprié:
zsh
:
array=(${(s:.:)var} # removes empty elements
array=("${(@s:.:)var}") # preserves empty elements
rc
:
array = ``(.){printf %s $var} # removes empty elements
fish
set array (string split . -- $var) # not for multiline $var