Nelle vecchie versioni bash
hai dovuto citare le variabili dopo <<<
. Ciò è stato risolto in 4.4. Nelle versioni precedenti, la variabile veniva suddivisa su IFS e le parole risultanti venivano unite nello spazio prima di essere archiviate nel file temporaneo che costituisce il <<<
reindirizzamento.
In 4.2 e prima, quando si reindirizzava builtin come read
o command
, tale suddivisione avrebbe persino preso l'IFS per quel builtin (4.3 risolto che):
$ 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
Quello risolto in 4.3:
$ bash-4.3 -c 'a=a.b.c.d; IFS=. read x <<< $a; echo "$x"'
a.b.c.d
Ma $a
è ancora soggetto alla suddivisione delle parole lì:
$ bash-4.3 -c 'a=a.b.c.d; IFS=.; read x <<< $a; echo "$x"'
a b c d
In 4.4:
$ bash-4.4 -c 'a=a.b.c.d; IFS=.; read x <<< $a; echo "$x"'
a.b.c.d
Per la portabilità alle versioni precedenti, cita la tua variabile (o usa da zsh
dove <<<
proviene in primo luogo e che non ha quel problema)
$ bash-any-version -c 'a=a.b.c.d; IFS=.; read x <<< "$a"; echo "$x"'
a.b.c.d
Si noti che tale approccio alla divisione di una stringa funziona solo per le stringhe che non contengono caratteri di nuova riga. Si noti inoltre che a..b.c.
sarebbe diviso in "a"
, ""
, "b"
, "c"
(senza svuotare ultimo elemento).
Per dividere stringhe arbitrarie puoi usare invece l'operatore split + glob (che lo renderebbe standard ed eviterebbe di archiviare il contenuto di una variabile in un file temporaneo <<<
):
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
o:
array=($var'') # in shells with array support
È ''
preservare un elemento vuoto finale se presente. Ciò dividerebbe anche un vuoto $var
in un elemento vuoto.
O utilizzare una shell con un operatore di divisione appropriato:
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