8

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

3
  • Do you have to use Bash? This sort of thing would be completely trivial with e.g. Ruby and YAML or Python and JSON or Lua or a bunch of other things. Commented Apr 19, 2014 at 7:19
  • I think it would be best for it to use Bash for what I am doing. I need to use the screen command and other things related to that. Commented Apr 19, 2014 at 7:21
  • Some more detail about what you are actually trying to do would be helpful. Commented Apr 19, 2014 at 14:21

4 Answers 4

7

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
Sign up to request clarification or add additional context in comments.

Comments

3

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

3 Comments

I like this answer but I find it more convenient to use array0[value1] instead of array0[0]. It better suits my needs. (Updated question)
@AJFerguson Nice to read this! I actually had to tweak things in a very unnatural way to fit your original requirements! Let me edit the answer to fit your new (and much more natural) requirements.
@AJFerguson changed (simplified) to fit your new requirements.
1

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.

1 Comment

I understand how to declare and use arrays but my problem is to parse arrays from a file.
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.