Shellscript INI-Parser
Manchmal müssen auch Shell-Scripte konfigurierbar sein. Um mehrere, zufällige Playlisten für meine Musiksammlung zu erstellen, wollte ich ein Script haben, welches eine Konfigurationsdatei auswertet und für jeden Abschnitt die gleiche Aktion ausführt. Gleichzeitig sollte es sich durch falsche INI-Direktiven nicht durcheinander bringen lassen und wie eine gängige INI-Datei aufgebaut sein.
Die Lösung ist folgendes Shellscript, welches eine INI-Datei abarbeitet und für jeden durch [Header]
eingeleiteten Abschnitt eine Callbackfunktion ausführt:
function ParseINI() {
inFile="$1"
callback="$2"
shift 2
params="$*"
if [ ! -f "$inFile" ]; then echo "File $inFile not found!"; exit; fi
local IFS="="
# Am Ende eine leere Section anhängen, damit auch der letzte Abschnitt verarbeitet wird
echo "[]"|cat "$inFile" -|sed 's/\\t/ /g;s/^ +//;s/ +$//;/^#/d;/^$/d'|while read name value; do
[ -z "$name" ] && continue
local IFS=" "
if [ "${name:0:1}" == "[" ]; then
counter=0
for param in $params; do
[ -z "${sectionParams[$counter]}" ] && sectionParams[$counter]="''"
let counter++
done
[ -z "$section" ] || eval $callback \\"$section\\" ${sectionParams[*]}
section=${name/'['/}
section=${section/']'/}
unset sectionParams
else
counter=0
for param in $params; do
if [ "$param" == "${name/ /}" ]; then
value=${value/# /}
value=${value/% /}
value=${value/#\\"/}
value=${value/%\\"/}
sectionParams[$counter]="'$value'"
fi
let counter++
done
fi
local IFS="="
done
}
Diese Funktion parsed eine INI-Datei mit folgendem Aufbau:
# Kommentar
[SectionHeader]
# Eventuell noch ein Kommentar
Name=Wert
Einrückungen werden ebenso entfernt wie am Schluss von Parametern hängende Leerzeichen. Auch Kommentarzeilen werden automatisch ignoriert.
Um die Funktion in einem Shellscript zu verwenden, müssen die Parameter folgendermaßen belegt werden:
Parameter | Wert |
---|---|
1 | Name der zu verarbeitenden INI-Datei. |
2 | Name der Callbackfunktion, welche für jeden INI-Abschnitt aufgerufen werden soll. |
3-x | Die Namen der INI-Werte in der Reihenfolge, in welcher sie an die Callbackfunktion übergeben werden sollen. |
Die Reihenfolge der Parameter im INI-Abschnitt ist nicht relevant. Das Script übergibt die Parameter immer in der Reihenfolge, welche im Aufruf von ParseINI angegeben wurde. Wird ein Parameter im entsprechenden Abschnitt nicht gesetzt, so wird ein leerer Wert übergeben. Das folgende Beispiel würde also die Datei /etc/genplaylist.conf
abarbeiten und für jeden Abschnitt die Bash-Funktion BuildPlaylist
aufrufen. Die Parameter werden dabei in folgender Reihenfolge übergeben:
Parameter | Wert |
---|---|
1 | Name des INI-Abschnitts. |
2 | INI-Parameter BasePath. |
3 | INI-Parameter RelPath. |
4 | INI-Parameter OutFile. |
ParseINI "/etc/genplaylist.conf" "BuildPlaylist" "BasePath" "RelPath" "OutFile"
Wichtig: Der Callback wird in einer Subshell ausgeführt. Es ist also nicht möglich, Umgebungsvariablen für die Hauptshell zu setzen!
Beispieldownload
Dieser Download enthält das Beispielscript und eine passende, kommentierte INI-Datei: herunterladen