Skip to content

Instantly share code, notes, and snippets.

@RoUS
Created August 16, 2014 01:03
Show Gist options
  • Save RoUS/54425ead07844daecf90 to your computer and use it in GitHub Desktop.
Save RoUS/54425ead07844daecf90 to your computer and use it in GitHub Desktop.
Bash function to read keys/values from an ini-style file section into an associative envariable
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# vim: ts=4:sw=4:noet
#
function _read_config_file() {
local _cfgfile='/dev/stdin'
local _section
local _varname='CONFIG_HASH'
local _line
local _key
local _value
local _cursection
local _sectfound
while [ -n "$*" ]; do
case "$1" in
-h | --help)
cat <<EOF
${FUNCNAME[0]} - Bash function to read settings from an ini-file
Usage:
${FUNCNAME[0]} [OPTIONS]
Options:
-h, --help Display this text.
-f FILE, --file=FILE Read from specified file.
Default is stdin.
-s SECTION, --section=SECTION Name of section to process in file.
Default is first section encountered.
-v VARNAME, --variable-name=VARNAME Environment variable into which
settings will be loaded. Default is
CONFIG_HASH
Example:
Given a file named 'test.ini' with the following contents:
--- snip 8<---
# Comment line
[section-1]
sec1key1 = sec1key1-value
sec1key2 = sec1key2-value
[section-2]
sec2key1 = sec2key1-value
sec2key2 = sec2key2-value
--- snip 8<---
here are the results from the following commands:
$ ${FUNCNAME[0]} < test.ini
=> CONFIG_HASH=([sec1key1]='sec1key1-value',[sec1key2]='sec1key2-value')
$ ${FUNCNAME[0]} -s section-1 < test.ini
=> CONFIG_HASH=([sec1key1]='sec1key1-value',[sec1key2]='sec1key2-value')
$ ${FUNCNAME[0]} -s section-2 < test.ini
=> CONFIG_HASH=([sec2key1]='sec2key1-value',[sec2key2]='sec2key2-value')
$ ${FUNCNAME[0]} -s section-2 -v Derpy < test.ini
=> Derpy=([sec2key1]='sec2key1-value',[sec2key2]='sec2key2-value')
EOF
return 0
;;
-f | --file | --file=*)
if [[ "$1" =~ --file= ]]; then
_cfgfile=${1#*=}
else
shift
_cfgfile=$1
fi
shift
;;
-s | --section | --section=*)
if [[ "$1" =~ --section= ]]; then
_section=${1#*=}
else
shift
_section=$1
fi
shift
;;
-v | --variable-name | --variable-name=*)
if [[ "$1" =~ --variable-name= ]]; then
_varname=${1#*=}
else
shift
_varname=$1
fi
shift
;;
*)
break
;;
esac
done
typeset -p ${_varname} 2> /dev/null || declare -A ${_varname}
{
while read _line; do
#
# Remove all leading and trailing whitespace from the line.
#
if [[ ${_line} =~ ^[[:space:]]*(.*?)[[:space:]]*$ ]]; then
_line=${BASH_REMATCH[1]}
fi
#
# If the first character of the trimmed line is a '#' it's a
# comment -- skip it.
#
if [[ "${_line:0:1}" == '#' ]] || [ -z "${_line}" ]; then
continue
fi
#
# See if this is a section header
#
if [[ ${_line} =~ ^\[([^][:space:]]*)\] ]]; then
_cursection=${BASH_REMATCH[1]}
#
# This is a section line. Here's what can happen:
#
# 1. We're not looking for a specific section, so we make
# *this* one our choice.
# 2. We *are* looking for a particular section but haven't
# found it, and this isn't it either. Keep looking.
# 3. This isn't our section, but we just finished reading
# ours -- so we're done.
# 4. This is our section -- start processing it.
#
#
# No section requested, so make this the one.
#
if [ -z "${_section}" ]; then
_section=${_cursection}
fi
#
# Is this the section we want?
#
if [[ "${_cursection}" == "${_section}" ]]; then
#
# Make a note that we've found it, and move on to the
# next line.
#
_sectfound=${_section}
elif [ -n "${_sectfound}" ]; then
#
# We found our section already, and this isn't it --
# so we've moved past it. We're done.
#
break
fi
continue
fi
if [ -z "${_sectfound}" ]; then
#
# We're not in a position to process any settings; we
# need to find the right section.
#
continue
fi
#
# Time to start reading settings. At this point, we're
# in the right section, and we've already ruled out comment
# and blank lines. We're only interested in 'key = value'
# lines at the moment; we ignore anything else.
#
if [[ "${_line}" =~ ^([^[:space:]]*)[[:space:]]*= ]]; then
_key=${BASH_REMATCH[1]}
_value=${_line#${_key}*=}
if [[ "${_value}" =~ ^[[:space:]]*(.*?)[[:space:]]*$ ]]; then
_value=${BASH_REMATCH[1]}
fi
fi
eval "${_varname}[${_key}]=\${_value}"
done
} < "${_cfgfile}"
}
@RoUS
Copy link
Author

RoUS commented Jan 15, 2015

[qualified] Thanks! I had a need to configure some bash stuff, and created an itch to scratch with this. :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment