Si Git est disponible et que vous êtes d'accord avec la contrainte de ne pas pouvoir utiliser de soulignements dans les noms de clés, vous pouvez l'utiliser git config
comme analyseur / éditeur INI à usage général.
Il gérera l'analyse de la paire clé / valeur de partout dans le =
et supprimera les espaces insignifiants, plus vous obtiendrez des commentaires (les deux ;
et #
) et tapez la contrainte essentiellement gratuitement. J'ai inclus un exemple de travail complet pour l'entrée de l'OP .ini
et la sortie souhaitée (tableaux associatifs Bash), ci-dessous.
Cependant, étant donné un fichier de configuration comme celui-ci
; mytool.ini
[section1]
inputdir = ~/some/dir
enablesomefeature = true
enablesomeotherfeature = yes
greeting = Bonjour, Monde!
[section2]
anothersetting = 42
… À condition que vous ayez juste besoin d'une solution rapide et sale, et que vous ne soyez pas marié avec l'idée d'avoir les paramètres dans un tableau associatif Bash, vous pouvez vous en sortir avec aussi peu que:
eval $(git config -f mytool.ini --list | tr . _)
# or if 'eval' skeeves you out excessively
source <(git config -f mytool.ini --list | tr . _)
qui crée des variables d'environnement nommées sectionname_variablename
dans l'environnement actuel. Cela, bien sûr, ne fonctionne que si vous pouvez être sûr qu'aucune de vos valeurs ne contiendra un point ou un espace (voir ci-dessous pour une solution plus robuste).
Autres exemples simples
Récupération de valeurs arbitraires, à l'aide d'une fonction shell pour enregistrer la saisie:
function myini() { git config -f mytool.ini; }
Un alias serait OK, ici aussi, mais ceux-ci ne sont normalement pas développés dans un script shell [ 1 ], et de toute façon les alias sont remplacés par des fonctions shell "pour presque tous les usages", [ 2 ], selon la page de manuel Bash .
myini --list
# result:
# section1.inputdir=~/some/dir
# section1.enablesomefeature=true
# section1.enablesomeotherfeature=yes
# section2.anothersetting=42
myini --get section1.inputdir
# result:
# ~/some/dir
Avec cette --type
option, vous pouvez "canoniser" des paramètres spécifiques sous forme d'entiers, de booléens ou de chemins (à expansion automatique ~
):
myini --get --type=path section1.inputdir # value '~/some/dir'
# result:
# /home/myuser/some/dir
myini --get --type=bool section1.enablesomeotherfeature # value 'yes'
# result:
# true
Exemple rapide et sale légèrement plus robuste
Rendre toutes les variables mytool.ini
disponibles comme SECTIONNAME_VARIABLENAME
dans l'environnement actuel, en préservant les espaces internes dans les valeurs clés:
source <(
git config -f mytool.ini --list \
| sed 's/\([^.]*\)\.\(.*\)=\(.*\)/\U\1_\2\E="\3"/'
)
Ce que fait l'expression sed, en anglais, c'est
- trouver un tas de caractères non-période jusqu'à une période, en se souvenant que comme
\1
, puis
- trouver un groupe de caractères jusqu'à un signe égal, en se souvenant que
\2
, et
- trouver tous les caractères après le signe égal comme
\3
- enfin, dans la chaîne de remplacement
- le nom de la section + le nom de la variable est en majuscules, et
- la partie valeur est entre guillemets, au cas où elle contient des caractères qui ont une signification spéciale pour le shell s'ils ne sont pas entre guillemets (comme les espaces)
Les séquences \U
et \E
dans la chaîne de remplacement (qui majuscule cette partie de la chaîne de remplacement) sont une sed
extension GNU . Sur macOS et BSD, vous utiliseriez simplement plusieurs -e
expressions pour obtenir le même effet.
Traiter les guillemets intégrés et les espaces dans les noms de section (ce qui git config
permet) est laissé comme exercice pour le lecteur.:)
Utilisation de noms de section comme clés dans un tableau associatif Bash
Donné:
; foo.ini
[foobar]
session=foo
path=/some/path
[barfoo]
session=bar
path=/some/path
Cela produira le résultat demandé par l'OP, simplement en réorganisant certaines des captures dans l'expression de remplacement sed, et fonctionnera bien sans GNU sed:
source <(
git config -f foo.ini --list \
| sed 's/\([^.]*\)\.\(.*\)=\(.*\)/declare -A \2["\1"]="\3"/'
)
Je prédis qu'il pourrait y avoir quelques défis avec la citation d'un .ini
fichier réel , mais cela fonctionne pour l'exemple fourni. Résultat:
declare -p {session,path}
# result:
# declare -A session=([barfoo]="bar" [foobar]="foo" )
# declare -A path=([barfoo]="/some/path" [foobar]="/some/path" )