How to create, access and manipulate associative arrays?

Asked

Viewed 233 times

2

I am using GNU-Bash on my Mingw terminal (bash --version: GNU bash, version 4.4.12(1)-release (i686-pc-msys)). I need to create a data dictionary to check if a new key has been found and associate this new key with an index. For this, I believe that the best solution would be an associative array.

However, I’m not getting this array to work!

For testing, I’m assigning incremental values to keys, one key per line. For example, I hope to get the following key/value pairs for that entry:

./array_assoc_platonico.sh << EOL
> bash
> scripting
> is
> tought
> as
> bash
> is
> pretty
> EOL
bash:1
scripting:2
is:3
tought:4
as:5
pretty:6

I don’t care about printing, but the contents of my array should be something like this.

My script so far:

#!/bin/bash

NEXT_IDX=1
while read line; do
    if [ "x${chaves[$line]}" = "x" ]; then
        # então chave nova
        chaves[$line]=$NEXT_IDX
        NEXT_IDX=$(( NEXT_IDX + 1 ))

        echo "$line:${chaves[$line]}"
    fi
done

However, my obtained output is being:

./array_assoc_falho.sh << EOL
> bash
> scripting
> is
> tought
> as
> bash
> is
> pretty
> EOL
bash:1

When I give one declare -p chaves at the end of the reading, I get the following:

declare -a chaves=([0]="1")

Where I am missing the use of the associative array in bash?

  • That’s the intention. I put in the first section what the terminal would print. But note that I need to manipulate the associative array, not just format the output

  • 1

    I’m the one who mosqued :)

1 answer

3


The correct is declare -A chaves, the variable "keys" will be treated as a matrix.

#!/bin/bash
declare -A chaves
NEXT_IDX=1
while read line; do
    if [ "x${chaves[$line]}" = "x" ]; then
        # então chave nova
        chaves[$line]=$NEXT_IDX
        NEXT_IDX=$(( NEXT_IDX + 1 ))

        echo "$line:${chaves[$line]}"
    fi
done

Exit:

bash:1
scripting:2
is:3
tought:4
as:5
pretty:6

Variables in Bash

  • When informing the parameter -a you create a indexed array, i.e., a variable containing a list where indexes are numbers.

    #!/bin/bash
    declare -a CARROS=("Gol" "Argo" "C3" "Saveiro")
    for ((I=0;I<3;I++)); do
        echo $I ${CARROS[I]};
    done
    

    The exit will be:

    0 Gol
    1 Argo
    2 C3
    
  • The parameter -A has its function equal to indexed array, the difference is in using a key string instead of numerical index.

  • The parameter -i sets the variable as an integer

    $ declare -i NUMERO=2018
    $ echo ${NUMERO}
    2018
    $ NUMERO+=2
    $ echo ${NUMERO}
    2020
    $ NUMERO="UM NOME QUALQUER" # IRÁ RETORNAR ZERO
    0
    
  • The parameters -l and -u serve to convert string in minuscules and capital letters.

    $ declare -l SITE="Pt.StaCkOverFlow.com"
    $ echo ${SITE}
    pt.stackoverflow.com
    $ declare -u SITE="pt.stackoverflow.com"
    $ echo ${SITE}
    PT.STACKOVERFLOW.COM
    
  • The parameter -r makes the read-only variable.

    $ declare -r VAR="Minha variável"
    $ echo ${VAR}
    Minha variável
    $ VAR="Novo conteúdo" # FOI DECLARADA COMO LEITURA, RETORNARA ERRO
    ./teste.sh: line 5: VAR: a variável permite somente leitura
    
  • The parameter -p serves to display attributes and values of a variable.

    $ declare -a VAR=("Corsa" "Gol" "Palio" "Uno")
    $ declare -p VAR
    declare -a VAR='([0]="Corsa" [1]="Gol" [2]="Palio" [3]="Uno")'
    
  • It’s a step closer, but it’s not the answer yet. I just tested it and got the same result on my computer. Are you sure it’s declare -a? That’s not another option declare?

  • Puts -A instead of -a ... See: https://www.gnu.org/software/bash/bash.pdf page 97

  • With -A was! Just waiting to update your reply to mark it as accepted

  • 1

    Extra kudos if you have a section explaining the creation of typed variables in Bash

  • Very complete your answer! It’s great

Browser other questions tagged

You are not signed in. Login or sign up in order to post.