Ar

Arrays em Bash

{one: "1 exercício", many: "%{count} exercícios", other: "%{count} exercícios"}

Sobre Arrays

O Bash disponibiliza dois tipos de parâmetros: valores "escalares" e arrays. Um valor escalar pode ser uma string ou um número; representa uma única "coisa".

Na maior parte das vezes, os valores escalares são suficientes para guardar os teus dados. Mas, por vezes, precisas de guardar uma lista de valores escalares. Nesse caso, vais usar um array.

Há dois tipos de arrays:

  • Os arrays indexados numericamente associam uma chave do tipo inteiro a um valor do tipo string. (Noutras linguagens, isto pode chamar-se "lista" ou "sequência".)
  • Os arrays associativos associam uma chave do tipo string a um valor do tipo string. (Noutras linguagens, isto pode chamar-se "mapa" ou "dicionário".)

As primeiras secções deste documento abordam os arrays indexados numericamente (daqui em diante, designados simplesmente por "arrays"). Os detalhes sobre os arrays associativos aparecem no final.

Caution

Os arrays do Bash só conseguem guardar valores escalares. Não é possível criar um array bidimensional (um array de arrays).

Declarar e inicializar uma variável de array

Podes inicializar um array atribuindo a uma variável uma lista de elementos entre parênteses (possivelmente vazia).

myarray=("one" "two" "three")

Tal como em qualquer atribuição de variável, não pode haver espaços em torno do sinal de igual.

Repara que não há vírgulas a separar os elementos; é uma lista de strings separada por espaços.

Na verdade, a quantidade de espaços dentro dos parênteses é totalmente arbitrária. Podes usar quebras de linha; usa tantas quantas quiseres 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 desta forma guarda a primeira string no índice zero, a seguinte no índice um, a seguinte no índice dois, e assim por diante.

É possível inicializar um "array esparso" especificando os índices de que precisas.

raindrops=([3]="Pling" [5]="Plang" [7]="Plong")
Note

Para reforçar: os índices dos arrays começam em zero. Este excerto produz o resultado "true":

myarray=("one" "two" "three")
[[ "${myarray[0]}" == "one" ]] && echo true || echo false

Podes 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 limitar-te a atribuir uma lista entre parênteses (possivelmente vazia) para inicializar a variável.

Aceder aos elementos de um array

Como viste na nota acima, a sintaxe para aceder a um elemento de um array é ${myarray[$index]}. O índice é indicado entre parênteses retos. As chavetas são obrigatórias.

Note

Nos arrays indexados numericamente, o índice é uma expressão aritmética. O manual do Bash afirma:

Dentro de uma expressão aritmética, as variáveis de shell também podem ser referenciadas pelo nome, sem usar a sintaxe de expansão de parâmetros.

Isto significa que o $ não é necessário para a expansão de variáveis "simples". Podes aceder aos elementos assim, o que é um pouco mais fácil de ler:

i=5
echo "${myarray[i]}"
# ..............^

Se o índice indicado não existir no array, o resultado da expansão é uma string vazia.

Atribuir valores a um array

Para atribuir um valor a uma entrada específica do array, usa esta sintaxe:

myarray[10]="hello"

Para acrescentar elementos a um array, usa o operador de atribuição por concatenação +=, com parênteses:

myarray+=("new element 1" "new element 2")

Iterar sobre um array

Normalmente vais precisar de iterar sobre os valores de um array. Usa um ciclo for (que viste no conceito Ciclos):

myarray=("one" "two" "three")
for value in "${myarray[@]}"; do
    echo "$value"
done

Repara na sintaxe especial para expandir o array: "${myarray[@]}" Esta forma de expansão de parâmetros substitui os valores do array por palavras separadas. É 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.

Esta expansão especial, em que o índice é uma arroba (@), só é especial dentro de aspas duplas.

Outras expansões especiais de parâmetros

Eis mais um par de sintaxes especiais de que precisamos para iterar sobre um array. Estão descritas no manual, em Shell Parameter Expansion.

Para saberes o comprimento de um array, usa ${#myarray[@]}, com um # antes do nome. O "comprimento" de um array é o número de elementos que contém.

Para obteres a lista de índices de um array, usa "${!myarray[@]}", com um ! antes do nome e a expansão entre aspas duplas. Nos arrays indexados numericamente, os índices são expandidos por ordem numérica.

Iterar sobre os índices de um array

Por vezes precisas do índice e também do valor. Há duas formas de o fazer.

  1. Quando sabes que os índices formam uma sequência ininterrupta, podes usar um ciclo for aritmético.

    for ((i = 0; i < ${#myarray[@]}; i++)); do
        echo "$i -> ${myarray[i]}"
    done
    

    Repara na sintaxe ${#myarray[@]}, com o caráter # à frente do nome do array. Como os arrays usam indexação a começar em zero, o último índice do array é uma unidade inferior ao comprimento do array.

  2. Quando o array é esparso, podes usar esta forma:

    for index in "${!raindrops[@]}"; do
        echo "$index -> ${raindrops[index]}"
    done
    

    Repara na sintaxe ${!myarray[@]}, com o caráter ! à frente do nome do array.

Inspecionar um array

Se quiseres ver o conteúdo de um array, usa o comando declare com a opção -p:

a=("the 'first' element"
   second
   third
   'the "last" element')
declare -p a

Isto mostra o conteúdo com o uso canónico de aspas do shell.

declare -a a=([0]="the 'first' element" [1]="second" [2]="third" [3]="the \"last\" element")

Arrays associativos

Para reforçar, os arrays associativos usam strings como índices, e não números. Tudo o que foi dito acima se aplica aos arrays associativos, mas com pequenas diferenças. Em geral, usamos o termo "chave" em vez de "índice": os arrays associativos associam chaves a valores.

Declarar um array associativo

Ao contrário dos arrays, os arrays associativos têm de ser declarados. Usa a opção -A do declare (ou local dentro de uma função):

declare -A mymap

myfunc() {
    local -A my_local_map
    # ...
}

Inicializar um array associativo

Os pares chave-valor são indicados dentro da lista entre parênteses:

mymap=([first]=foo [second]=bar [third]=baz)
declare -p mymap

Isto produz:

declare -A mymap=([second]="bar" [first]="foo" [third]="baz")
Note

Repara que os arrays associativos não têm ordem.

A declaração e a inicialização podem acontecer numa só linha.

declare -A mymap=([first]=foo [second]=bar [third]=baz)

Nas 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)

Aceder aos valores

Usa-se a mesma sintaxe de antes para aceder aos elementos: ${mymap[$key]}.

As chaves dos arrays associativos não são avaliadas num contexto aritmético. É necessária a sintaxe habitual de expansão de parâmetros.

Atribuir valores a um array associativo

A atribuição usa a mesma sintaxe de antes:

mymap[$key]="$value"

Iterar

Podes usar um ciclo for value in "${mymap[@]}" para iterar. No entanto, normalmente também queres a chave juntamente com o valor.

Usa a sintaxe "${!mymap[@]}" que vimos acima.

for key in "${!mymap[@]}"; do
    echo "$key -> ${mymap[$key]}"
done

Isto produz

second -> bar
first -> foo
third -> baz

Voltando a sublinhar: as chaves não têm qualquer ordem.

Editar via GitHub A ligação abre numa nova janela ou separador