Pergunta

I need to have an array for each "section" in the file containing:

[array0]
value1=asdf
value2=jkl

[array1]
value1=1234
value2=5678

I want to be able to retrieve these values like this:

echo ${array0[value1]}
echo ${array0[value2]}

echo ${array1[value1]}
echo ${array1[value2]}

Any thoughts on how to accomplish this? (Explanations would be a bonus)

I've already read these anwsers but none do exactly what I want to do.

Read a config file in BASH without using "source"

BASH Parsing variables from config file

Array like data structure in bash (config file)?

Foi útil?

Solução

with bash v4, using associative arrays, store the properties from the config file as actual bash variables:

$ while read line; do 
    if [[ $line =~ ^"["(.+)"]"$ ]]; then 
        arrname=${BASH_REMATCH[1]}
        declare -A $arrname
    elif [[ $line =~ ^([_[:alpha:]][_[:alnum:]]*)"="(.*) ]]; then 
        declare ${arrname}[${BASH_REMATCH[1]}]="${BASH_REMATCH[2]}"
    fi
done < config.conf

$ echo ${array0[value1]}
asdf

$ echo ${array1[value2]}
5678

$ for i in "${!array0[@]}"; do echo "$i => ${array0[$i]}"; done
value1 => asdf
value2 => jkl

$ for i in "${!array1[@]}"; do echo "$i => ${array1[$i]}"; done
value1 => 1234
value2 => 5678

Outras dicas

One eval-free, 100% pure Bash possibility:

#!/bin/bash

die() {
   printf >&2 "%s\n" "$@"
   exit 1
}

aryname=''
linenb=0
while read line; do
   ((++linenb))
   if [[ $line =~ ^[[:space:]]*$ ]]; then
      continue
   elif [[ $line =~ ^\[([[:alpha:]][[:alnum:]]*)\]$ ]]; then
      aryname=${BASH_REMATCH[1]}
      declare -A $aryname
   elif [[ $line =~ ^([^=]+)=(.*)$ ]]; then
      [[ -n aryname ]] || die "*** Error line $linenb: no array name defined"
      printf -v ${aryname}["${BASH_REMATCH[1]}"] "%s" "${BASH_REMATCH[2]}"
   else
      die "*** Error line $linenb: $line"
   fi
done

Reads on standard input. If you want to read from a file, change the done by:

done < "filename"

Lines of the form

space and funnŷ sÿmbòl=value that will have an equal sign: look = it's funny

are allowed

You can declare array in bash scripts with

declare -a <array_name>=(value1 value2 value 3)

Then you can use them like this

echo ${<array_name>[index]}

Edit:

Ok, to construct arrays from config file. I would recommend to have a different file for each array you would like to create.

So here are the steps

1.config file (create a file and place your values in it)

100
200
300

2.script file (read values from file and prepare an array)

    array=()

    #setup array
    while IFS=$'\n' read -a config
    do
      array+=(${config})
    done < file_name

    #access values
    echo ${array[0]}
    echo ${array[1]}

IFS denotes the delimiter
-a specifies the array name you want to extract to, so that you can access them inside the while loop.

I am about to go out, but I think you can do something like this (untested) and maybe someone clever , like @anubhava, will pick it up and finish it off...

eval $(gawk -F= '/^\[/{name=gensub(/\[|\]/,"","g");x=0} /=/{print "name[",x++,"]=",$2," "}' config)

Basically, when it sees a line starting with "[" it picks up the array name in the variable name and strips off the square brackets with gensub(). Then, when it sees a line with "=" in it, it outputs the array name and an increasing index "x" for eval to pick up.

Gotta dash - look at the examples for stat -s here.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top