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 “^[#;]”
}