Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm trying to convert an ini file into bash array variables. The sample ini is as below:



so these become:


and so on.

Right now, I could come up with only this command

awk -F'=' '{ if ($1 ~ /^\[/) section=$1; else if ($1 !~ /^$/) print $1 section "=" $2 }'

Also, another problem is, it doesn't take spaces near = into consideration. I think sed is probably better suited for this job but I don't know how to hold and store a temporary variable for the section name in sed.

So any idea how to do this?

share|improve this question
If there's other efficient way to do this, feel free to post your solution too :) – Flint Jan 1 '12 at 9:24
For simple solution, check: How do I grab an INI value within a shell script? at stackoverflow SE. – kenorb Mar 1 '15 at 15:19
up vote 4 down vote accepted

Gawk accepts regular expressions as field delimiters. The following eliminates spaces around the equal sign, but preserves them in the rest of the line. Quotes are added around the value so those spaces, if any, are preserved when the Bash assignment is performed. I'm assuming that the section names will be numeric variables, but if you're using Bash 4, it would be easy to adapt this to use associative arrays with the section names themselves as the indices.

awk -F ' *= *' '{ if ($1 ~ /^\[/) section=$1; else if ($1 !~ /^$/) print $1 section "=" "\"" $2 "\"" }'

Note that you may want to also do the space removal that Khaled shows (on only $1 and section) since Bash variable names can't contain spaces.

Also, this method won't work if the values contain equal signs.

Another technique would be to use a Bash while read loop and perform the assignments as the file is read, using declare which is safe from most malicious content.

barfoo=2  # or you could increment an index variable each time a section is found
while IFS='= ' read var val
    if [[ $var == \[*] ]]
    elif [[ $val ]]
        declare "$var$section=$val"
done < filename

Again, associative arrays could fairly easily be supported.

share|improve this answer
Very nice info and I particularly like the second technique since it uses bash built in function, instead of relying on external command. – Flint Jan 2 '12 at 2:07

Here's a pure bash solution.

This is a new and improved version of what chilladx posted:

For a really easy to follow initial example: After you download this, just copy the files bash-ini-parser, and scripts/file.ini to the same directory, then create a client test script using the example I've provided below to that same directory as well.

source ./bash-ini-parser
cfg_parser "./file.ini"
echo "var2=$var2"
echo "var5[*]=${var5[*]}"
echo "var5[1]=${var5[1]}"

Here are some further improvements I made to the bash-ini-parser script...

If you want to be able to read ini files with Windows line endings as well as Unix, add this line to the cfg_parser function immediately following the one which reads the file:

ini=$(echo "$ini"|tr -d '\r') # remove carriage returns

If you want to read files which have restrictive access permissions, add this optional function:

# Enable the cfg_parser to read "locked" files
function sudo_cfg_parser {

    # Get the file argument

    # If not "root", enable the "sudo" prefix
    if [[ $EUID -ne 0 ]]; then sudoPrefix=sudo; fi

    # Save the file permissions, then "unlock" the file
    saved_permissions=$($sudoPrefix stat -c %a $file)
    $sudoPrefix chmod 777 $file

    # Call the standard cfg_parser function
    cfg_parser $file

    # Restore the original permissions
    $sudoPrefix chmod $saved_permissions $file  
share|improve this answer

I would use simple python script for this job since it has built in INI parser:

#!/usr/bin/env python

import sys, ConfigParser

config = ConfigParser.ConfigParser()

for sec in config.sections():
    print "declare -A %s" % (sec)
    for key, val in config.items(sec):
        print '%s[%s]="%s"' % (sec, key, val)

and then in bash:


# load the in.ini INI file to current BASH - quoted to preserve line breaks
eval "$(cat in.ini  | ./"

# test it:
echo ${barfoo[session]}

Sure, there are shorter implementations in awk, but I think this is more readable and easier to maintain.

share|improve this answer
In bash versions prior to 4.2 it is necessary to declare an associate array before filling it, e.g. print "declare -A %s" % (sec) – Felix Eve May 22 '15 at 3:29

Or you can use this ini parser in bash.

share|improve this answer
I'd love to use this, but I get syntax errors. I'm also confused by the use of cfg.parser vs cfg_parser in the example implementation. Can you post some help with this? – BuvinJ Jan 21 at 16:31
Never mind. It looks like that syntax with the . vs _ was simply wrong. I found an updated and FUNCTIONAL version of this with better examples. See my post. – BuvinJ Jan 21 at 16:51

If you want to eliminate the extra spaces, you can use the built-in function gsub. For example, you can add:

gsub(/ /, "", $1);

This will remove all spaces. If you want to remove spaces at the beginning or end of token, you can use

gsub(/^ /, "", $1);
gsub(/ $/, "", $1);
share|improve this answer
Cool tricks. Didn't know there's such a built-in function :) – Flint Jan 2 '12 at 1:34

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.