Bash: Ini Dateien Parsen/ Lesen
Bei einigen Servern habe ich einen Cronjob, der ruft ein Shellskript auf, welches den IST Zustand einiger Dienste auflistet. Also, auf einem Server, welche Mysql- und Postgres-Datenbankschemata es gibt, auf dem nächsten welche Apache VHosts existieren und auf dem Fileserver welche Samba-Shares usw.
Schlussendlich landet es auf einem Wiki (Dokuwiki in diesem Fall - hier sind die Seiten Txt-Dateien im Filesystem - das macht die Sache sehr einfach).
Beim Samba Server war es bis anhin recht unschön, weil umständlich gecodet. Nun habe ich 3 kleine Funktionen hinzugefügt, mit denen ich (endlich :-)) eine INI Datei parsen kann.
Die Funktionen kann man in eine Datei mit Leserechten (ohne Execute-Recht) auslagern, die man im Skript sourct (per source oder Punkt-Kommando).
- _getInisections [Name der Ini-Datei]
listet alle Sektionstitel auf - _getInisectiondata [Name der Ini-Datei] [Name der Sektion]
listet die angegebene Sektion auf. Mit dieser Ausgabe sieht man eine Sektion alleinstehend - und kann sich die Variablen herausziehen … aber wenn man die Variablen kennt, gibt es noch die nächste Funktion - _getIniValue [Name der Ini-Datei] [Name der Sektion] [Name der Variable]
gibt den Wert einer Variable aus der angegebenen Sektion zurück
In der Samba-Konfiguration (/etc/samba/smb.conf) sind die Variablen und Werte nicht zwingend ab Zeilenanfang - daher sind im Regex Leerzeichen und Tabs hinzugefügt.
# Helper for ini files: get all sections # param1 - name of the ini file function _getInisections(){ local myfile=$1 grep "^\[" $myfile | sed 's,^\[,,' | sed 's,\],,' } # Helper for ini files: get all content inside a section # param1 - name of the ini file # param2 - name of the section in ini file function _getInisectiondata(){ local myfile=$1 local mysection=$2 mysection=$( sed "s#/#\/#g" <<< "$mysection" ) sed -e "0,/^\[${mysection}\]/ d" -e '/^\[/,$ d' $myfile | grep -v "^[#;]" } # Helper for ini files: get a value of a variable in a given section # param1 - name of the ini file # param2 - name of the section in ini file # param3 - name of the variable to read function _getIniValue(){ local myfile=$1 local mysection=$2 local myvarname=$3 _getInisectiondata ${myfile} ${mysection} | grep "[^\a][\ \t]*${myvarname}[\ \t]*=.*" | cut -f 2 -d "=" | sed -e 's,^\ *,,' }
Und als Anwendungsbeispiel: ein Snippet mit einem Loop über die Samba-Konfiguration. Ausgegeben wird eine Tabelle mit Name des Shares, Beschreibung (Wert “comment”) und Pfad des Shares (Wert “path”):
smbconf=/etc/samba/smb.conf # Ausgabe des Tabellen-Header in Wiki-Syntax echo "^Share^Kommentar^Pfad^" # Loop ueber alle Sektionen for mysection in `_getInisections $smbconf | grep -v global` do # Ini-Werte aus der Sektion lesen myComment=`_getIniValue ${smbconf} ${mysection} "comment"` mypath=`_getIniValue ${smbconf} ${mysection} "path"` # Ausgabe der Tabellen-Zeile - Pipes sind Spaltentrenner echo "|${mysection}|${myComment}|${mypath}|" done
UPDATES:
- 15.05.2019: Korrektur der fehlenden Backslahes (die wirft das Blogtool immer raus, wenn man es nicht als Html-Entity schreibt) plus verbessertes Handling mit laschen Regex und Leerzeichen. Danke an Frank!
- 04.03.2021: Sektionen mit eckigen Klammern aus Kommentaren ignorieren. Zusätzlich werden Kommentare mit Semikolon am Anfang ebenfalls ignoriert. Ein local macht eine Variable nur innerhalb der Funktion bekannt.
- 09.02.2022 Update von _getIniValue: [^\a] statt ^
- 19.03.2023: Ein Follower Projekt: Ich habe aus der class like Bash Funktionen erstellt. Mit Validator und anständiger Dokumentation https://www.axel-hah … docs/bash_iniparser/
Donnerstag, Mai 9, 2019 - 12:25:19
Tolle Sache, und nicht ueberfrachtet mit Sonderfunktionen sondern schoen einfach. Allerdings musste ich erst alle “[” und “]” in den grep- und sed-Kommandos escapen bevor es lief. Vorher spuckte jedes Kommando Fehler aus: “Invalid regular expression” fuer grep und “unterminated `s’ command” fuer sed.
Dienstag, Februar 23, 2021 - 12:03:59
Ja, super Teil!
Ein Problem ist mir aufgefallen: Wenn im .ini File in einem Kommentar die Section erwähnt wird, dann scheitert die Abfrage.
Also z.B. folgender Kommentar “# Section [Global]: Hier sind alle globalen Einstellungen” bringt das durcheinander…
Montag, Januar 22, 2024 - 15:03:03
Wenn ich jetzt sectionen habe wie z.b.
[/Script/Pal.PalGameWorldSettings]
brint er mir sed Fehler
Donnerstag, August 15, 2024 - 11:45:29
Danke für den Hinweis!
Das Herauslösen einer ganzen Sektion mit dem sed arbeitet mit einem Regex als Suchstring. Da ich einen Forward-Slash als Trenner verwende, muss im Suchstring in der Variable mysection der Forward-Slash escaped werden:
function _getInisectiondata(){
local myfile=$1
local mysection=$2
mysection=$( sed “s#/#\\\/#g” <<< “$mysection” )
sed -e “0,/^\[${mysection}\]/ d” -e ‘/^\[/,$ d’ $myfile | grep -v “^[#;]”
}