O Bash oferece dois tipos de parâmetros: valores "escalares" e arrays. Um valor escalar pode ser uma string ou um número; ele representa uma única "coisa".
Na maioria das vezes, valores escalares são suficientes para guardar seus dados. Mas, às vezes, você precisa armazenar uma lista de valores escalares. Nesse caso, você vai usar um array.
Existem dois tipos de arrays:
As primeiras seções deste documento abordam os arrays indexados numericamente (daqui em diante, chamados simplesmente de "arrays"). Os detalhes sobre arrays associativos aparecem no final.
Os arrays do Bash podem armazenar apenas valores escalares. Não há como criar um array bidimensional (array de arrays).
Você pode inicializar um array atribuindo uma lista de elementos entre parênteses (possivelmente vazia) a uma variável.
myarray=("one" "two" "three")
Como acontece com toda atribuição de variável, não pode haver espaços em volta do sinal de igual.
Repare que não há vírgulas separando os elementos; é uma lista de strings separadas por espaços em branco.
Na verdade, a quantidade de espaços em branco dentro dos parênteses é totalmente livre. Quebras de linha são permitidas; use quantas quiser para melhorar a legibilidade.
myarray=(
"first element"
"second element"
"this is the last element"
)
Atribuir uma lista de strings a uma variável de array dessa forma guarda a primeira string no índice zero, a próxima string no índice um, a seguinte no índice dois, e assim por diante.
É possível inicializar um "array esparso" especificando os índices de que você precisa.
raindrops=([3]="Pling" [5]="Plang" [7]="Plong")
Recapitulando: os índices de arrays começam em zero. Este trecho imprime "true":
myarray=("one" "two" "three")
[[ "${myarray[0]}" == "one" ]] && echo true || echo false
Você pode usar o comando declare (ou local dentro de uma função) para indicar que uma variável vai conter um array.
declare -a myarray
É mais idiomático simplesmente atribuir uma lista entre parênteses (talvez vazia) para inicializar a variável.
Como você viu na nota acima, a sintaxe para acessar um elemento de um array é ${myarray[$index]}.
O índice é dado entre colchetes.
As chaves são obrigatórias.
Para arrays indexados numericamente, o índice é uma expressão aritmética. O manual do Bash afirma:
Dentro de uma expressão aritmética, variáveis do shell também podem ser referenciadas pelo nome, sem usar a sintaxe de expansão de parâmetros.
Isso significa que o $ não é necessário para a expansão "simples" de variáveis.
Você pode acessar os elementos assim, o que é um pouco mais fácil de ler:
i=5
echo "${myarray[i]}"
# ..............^
Se o índice informado não existir no array, o resultado da expansão é uma string vazia.
Para atribuir a uma entrada específica do array, use esta sintaxe:
myarray[10]="hello"
Para acrescentar a um array, use o operador de atribuição concatenante += e use parênteses:
myarray+=("new element 1" "new element 2")
Normalmente você vai precisar iterar sobre os valores de um array.
Use um laço for (que você viu no conceito Laço):
myarray=("one" "two" "three")
for value in "${myarray[@]}"; do
echo "$value"
done
Repare na sintaxe especial para expandir o array: "${myarray[@]}"
Essa forma de expansão de parâmetros substitui os valores do array como palavras separadas.
Ela é mais ou menos equivalente a:
for value in "${myarray[0]}" "${myarray[1]}" ... "${myarray[n]}"
A forma "${myarray[@]}" funciona com arrays esparsos, expandindo apenas os valores definidos.
Essa expansão especial, em que o índice é uma arroba (@), só é especial dentro de aspas duplas.
Aqui estão mais alguns detalhes de sintaxe especial de que precisamos para iterar sobre um array. Eles estão descritos no manual em Expansão de parâmetros do shell.
Para descobrir o comprimento de um array, use ${#myarray[@]}, com um # antes do nome.
O "comprimento" de um array é o número de elementos nele.
Para extrair a lista de índices de um array, use "${!myarray[@]}", com um ! antes do nome e a expansão entre aspas duplas.
Para arrays indexados numericamente, os índices são expandidos em ordem numérica.
Às vezes você precisa do índice além do valor. Há algumas formas de fazer isso.
Quando você sabe que os índices formam uma sequência ininterrupta, pode usar um laço for aritmético.
for ((i = 0; i < ${#myarray[@]}; i++)); do
echo "$i -> ${myarray[i]}"
done
Repare na sintaxe ${#myarray[@]}, com o caractere # na frente do nome do array.
Como os arrays começam no índice zero, o último índice do array é uma unidade menor que o comprimento do array.
Quando o array é esparso, você pode usar esta forma:
for index in "${!raindrops[@]}"; do
echo "$index -> ${raindrops[index]}"
done
Repare na sintaxe ${!myarray[@]}, com o caractere ! na frente do nome do array.
Se você quiser ver o conteúdo de um array, use o comando declare com a opção -p:
a=("the 'first' element"
second
third
'the "last" element')
declare -p a
Isso imprime o conteúdo com as aspas no formato canônico do shell.
declare -a a=([0]="the 'first' element" [1]="second" [2]="third" [3]="the \"last\" element")
Recapitulando, arrays associativos usam strings como índices, não números. Tudo o que foi escrito acima vale para arrays associativos, mas com pequenas diferenças. Em geral, usamos o termo "chave" e não "índice": arrays associativos associam chaves a valores.
Diferentemente dos arrays, os arrays associativos precisam ser declarados.
Use a opção -A do declare (ou de local dentro de uma função):
declare -A mymap
myfunc() {
local -A my_local_map
# ...
}
Os pares chave-valor são especificados dentro da lista entre parênteses:
mymap=([first]=foo [second]=bar [third]=baz)
declare -p mymap
Isso imprime:
declare -A mymap=([second]="bar" [first]="foo" [third]="baz")
Lembre-se de que os arrays associativos não têm ordem.
A declaração e a inicialização podem acontecer em uma única linha.
declare -A mymap=([first]=foo [second]=bar [third]=baz)
Em versões recentes do Bash, a inicialização pode usar uma lista (key value key value ...).
declare -A mymap=(first foo second bar third baz)
A mesma sintaxe de antes é usada para acessar elementos: ${mymap[$key]}.
As chaves de arrays associativos não são avaliadas em contexto aritmético. É preciso usar a sintaxe usual de expansão de parâmetros.
A atribuição usa a mesma sintaxe de antes:
mymap[$key]="$value"
Você pode usar um laço for value in "${mymap[@]}" para iterar.
No entanto, normalmente você também quer a chave junto com o valor.
Use a sintaxe "${!mymap[@]}" que vimos acima.
for key in "${!mymap[@]}"; do
echo "$key -> ${mymap[$key]}"
done
Isso imprime
second -> bar
first -> foo
third -> baz
Vale reforçar: as chaves não têm ordem.