Em um roteiro Bash eu gostaria de dividir uma linha em pedaços e armazená-los em uma matriz.
A linha:
Paris, France, Europe
Eu gostaria de tê-los numa série como esta:
array[0] = Paris
array[1] = France
array[2] = Europe
Eu gostaria de usar código simples, o comando's speed doesn't matter. Como eu posso fazer isso?
IFS=', ' read -r -a array <<< "$string"
Note que os caracteres em `$IFS' são tratados individualmente como separadores, de modo que, neste caso, os campos podem ser separados por e uma vírgula ou um espaço, em vez da sequência dos dois caracteres. Curiosamente, campos vazios são't criados quando o espaço em vírgula aparece na entrada porque o espaço é tratado especialmente.
Para aceder a um elemento individual:
echo "${array[0]}"
Para iterar sobre os elementos:
for element in "${array[@]}"
do
echo "$element"
done
Para obter tanto o índice como o valor:
for index in "${!array[@]}"
do
echo "$index ${array[index]}"
done
O último exemplo é útil porque as matrizes Bash são esparsas. Em outras palavras, você pode apagar um elemento ou adicionar um elemento e então os índices não são contíguos.
unset "array[1]"
array[42]=Earth
Para obter o número de elementos de uma matriz:
echo "${#array[@]}"
Como mencionado acima, as matrizes podem ser esparsas, então você não deve usar o comprimento para obter o último elemento. Aqui's como você pode no Bash 4.2 e mais tarde:
echo "${array[-1]}"
em qualquer versão do Bash (de algum lugar depois de 2.05b):
echo "${array[@]: -1:1}"
Os maiores offsets negativos selecionam mais longe do fim da matriz. Observe o espaço antes do sinal de menos na forma antiga. É necessário.
Aqui está uma maneira sem definir 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
A ideia é usar a substituição de cordas:
${string//substring/replacement}
para substituir todas as combinações de $substring por espaço branco e depois usar a string substituída para inicializar um array:
(element1 element2 ... elementN)
Nota: esta resposta faz uso do operador split+glob. Assim, para evitar a expansão de alguns caracteres (como *
) é uma boa idéia pausar o globbing para este script.
Às vezes me aconteceu que o método descrito na resposta aceita não funcionava't, especialmente se o separador é um retorno de carruagem.
Nesses casos resolvi desta forma:
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