Created
June 24, 2020 13:46
-
-
Save egladman/e2f3b0ee391cba1c7deb12452799327e to your computer and use it in GitHub Desktop.
parse ini files with pure bash. Read more about it here: eli.gladman.cc/blog/2020/06/23/parsing-ini-file-with-bash.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
parse_ini() { | |
# Usage: parse_ini "path/to/file" | |
# parse_ini "path/to/file" false | |
# By default variables will be evaluated. Disable this by passing in "false" | |
local regex_contains_variable="^([a-zA-Z0-9_]{1,})([[:space:]]\=[[:space:]])(.*)$" | |
local regex_contains_wrapped_quotes="^([\"\'])(.*)([\"\'])$" | |
local regex_contains_inside_quotes="^([\"])(.*)([\"])(.*)([\"])$" | |
local multi_line="" | |
while IFS='' read -r line || [[ -n "$line" ]]; do | |
# Strip trailing comments from line | |
if [[ "$line" == *[[:space:]]\#* ]]; then | |
line="${line%%\#*}" | |
fi | |
case "$line" in | |
\#*|\;*) | |
# Ignore commented line | |
continue | |
;; | |
\[*|*\]) | |
# There is no explicit "end of section" delimiter; sections end at | |
# the next section declaration | |
section="${line##\[}" # Strip left bracket | |
section="${section%%\]}_" # Strip right bracket | |
continue | |
;; | |
*\\) | |
multi_line+="${line%%\\}\n" | |
;; | |
*) | |
if [[ -n "$multi_line" ]]; then | |
multi_line+="$line" | |
line="$multi_line" | |
multi_line="" | |
fi | |
;; | |
esac | |
if [[ ! "$line" =~ $regex_contains_variable ]] || [[ -n "$multi_line" ]]; then | |
continue | |
fi | |
local name val | |
val="${line/*\= }" # Everything after the equals sign | |
name="${section}${line/$val}" # Invert match. This way we know we've captured everything | |
name="${name%% *}" # Remove trailing whitespace and equals sign | |
# Wrap 'val' in quotes if they're missing | |
if [[ ! "$val" =~ $regex_contains_wrapped_quotes ]]; then | |
val="\"$val\"" | |
fi | |
if [[ "$val" =~ $regex_contains_inside_quotes ]]; then | |
local tmp | |
tmp="${val##\"}" # Strip left quote | |
tmp="${tmp%%\"}" # Strip right quote | |
tmp="${tmp//\"/\\\"}" # Escape all quotes | |
val="\"$tmp\"" # Add back the wrapped quotes | |
unset tmp | |
fi | |
local declaration | |
declaration="$(printf '%b\n' "$name=$val")" | |
[[ "$2" == "false" ]] || eval "$declaration" | |
printf '%s\n' "$declaration" | |
done < "$1" | |
} | |
parse_ini "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
MIT Licensed.