Skip to content

Instantly share code, notes, and snippets.

@ernstki
Last active July 27, 2023 22:45
Show Gist options
  • Save ernstki/5147c5e616b612d0cbf2618343b7dc21 to your computer and use it in GitHub Desktop.
Save ernstki/5147c5e616b612d0cbf2618343b7dc21 to your computer and use it in GitHub Desktop.
parse a Windows-style .ini file into a Bash associative array declaration
#!/usr/bin/sed -nf
##
## parse a Windows-style .ini file into key-value pairs that can be 'eval'd
## into a Bash associative array declaration
##
## Usage:
## $ eval "declare -A cfg=( $(ini2assoc config.ini) )"
## $ echo "section.keyname = ${cfg[section.keyname]}"
##
## Input:
## A Windows-style .ini file with unquoted, single-line values; '#' and
## ';' are supported as comment characters and blank lines are ignored
##
## Returns:
## Bash associative array syntax of the form: [section.keyname]="value"
##
## Notes:
## - no special care is taken to escape quote characters within values,
## which could result in a Bash syntax error
## - this script does only incidental input sanitization (stripping
## anything after a semicolon); use only with .ini files you wrote and
## have protected from unintentional modification
##
## Author:
## Dr. Michaël Grünewald (https://github.com/michipili)
## with modifications by Kevin Ernst (ernstki -at- mail.uc.edu)
##
## Source(s):
## https://gist.github.com/ernstki/5147c5e616b612d0cbf2618343b7dc21
## https://michipili.github.io/shell/2015/06/05/shell-configuration-file.html
##
## TODOs (exercises left for the reader):
## - support interpolation of previously-defined keys, e.g. '${keyname}'
## - recognize "\" as line continuation character
## - properly escape quote characters within values
## - try harder to sanitize untrusted input, so it can be safely 'eval'd
##
# key-value pairs outside any section are assigned to 'default' section
1 {
x
s/^/[default./
x
}
# ignore comments and blank lines; trim trailing comments
/^[;#]/d
/^[[:space:]]*$/d
s/[[:space:]]*[;#].*$//
# format keys so they can be fetched from the resulting associative array like
# this: ${cfg[section.keyname]} -> value
# first, store section name as '[section.'; later we'll add 'keyname]='
/^\[/ {
s/\[\(.*\)\]/[\1./
x
b
}
# now, for key=value lines, trim leading whitespace, add 'keyname]=' to make
# this a valid key for Bash associative arrays, then prepend the section name
# from the hold buffer
/=/ {
s/^[[:space:]]*//
s/[[:space:]]*=[[:space:]]*/]="/
G
s/\(.*\)\n\(.*\)/\2\1"/
p
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment