In uno script Bash vorrei dividere una linea in pezzi e memorizzarli in un array.
La linea:
Paris, France, Europe
Vorrei averli in un array come questo:
array[0] = Paris
array[1] = France
array[2] = Europe
Vorrei usare un codice semplice, la velocità del comando non ha importanza. Come posso fare?
IFS=', ' read -r -a array <<< "$string"
Si noti che i caratteri in $IFS
sono trattati individualmente come separatori, quindi in questo caso i campi possono essere separati da e una virgola o uno spazio piuttosto che dalla sequenza dei due caratteri. È interessante notare che i campi vuoti non vengono creati quando compare la virgola nell'input perché lo spazio viene trattato in modo speciale.
Per accedere ad un singolo elemento:
echo "${array[0]}"
Per iterare sugli elementi:
for element in "${array[@]}"
do
echo "$element"
done
Per ottenere sia l'indice che il valore:
for index in "${!array[@]}"
do
echo "$index ${array[index]}"
done
L'ultimo esempio è utile perché gli array Bash sono sparsi. In altre parole, si può cancellare un elemento o aggiungere un elemento e quindi gli indici non sono contigui.
unset "array[1]"
array[42]=Earth
Per ottenere il numero di elementi in un array:
echo "${#array[@]}"
Come detto sopra, gli array possono essere sparsi, quindi non si dovrebbe usare la lunghezza per ottenere l'ultimo elemento. Ecco come è possibile in Bash 4.2 e successivi:
echo "${array[-1]}"
in qualsiasi versione di Bash (da qualche parte dopo la 2.05b):
echo "${array[@]: -1:1}"
Gli offset negativi più grandi selezionano più lontano dalla fine dell'array. Si noti lo spazio prima del segno meno nella vecchia forma. È necessario.
Ecco un modo senza impostare IFS:
string="1:2:3:4:5"
set -f # avoid globbing (expansion of *).
array=(${string//:/ })
for i in "${!array[@]}"
do
echo "$i=>${array[i]}"
done
L'idea è di usare la sostituzione delle stringhe:
${string//substring/replacement}
per sostituire tutte le corrispondenze di $substringa con uno spazio bianco e poi usare la stringa sostituita per inizializzare un array:
(element1 element2 ... elementN)
Nota: questa risposta fa uso dell'operatore split+glob. Quindi, per prevenire l'espansione di alcuni caratteri (come *
) è una buona idea mettere in pausa il globbing per questo script.
A volte mi è capitato che il metodo descritto nella risposta accettata non funzionasse, specialmente se il separatore è un ritorno a capo; In quei casi ho risolto in questo modo:
string='first line
second line
third line'
oldIFS="$IFS"
IFS='
'
IFS=${IFS:0:1} # this is useful to format your code with tabs
lines=( $string )
IFS="$oldIFS"
for line in "${lines[@]}"
do
echo "--> $line"
done