Si tiene Git disponible y está de acuerdo con la restricción de no poder usar guiones bajos en los nombres de clave, puede usarlo git configcomo un analizador / editor INI de propósito general.
Manejará el análisis del par clave / valor de todo el =espacio en blanco y descartará insignificantes, además obtendrá comentarios (ambos ;y #) y la coerción de tipo básicamente de forma gratuita. He incluido un ejemplo de trabajo completo para la entrada del OP .iniy la salida deseada (matrices asociativas de Bash), a continuación.
Sin embargo, dado un archivo de configuración como este
; mytool.ini
[section1]
inputdir = ~/some/dir
enablesomefeature = true
enablesomeotherfeature = yes
greeting = Bonjour, Monde!
[section2]
anothersetting = 42
... siempre que solo necesite una solución rápida y sucia, y no esté casado con la idea de tener la configuración en una matriz asociativa de Bash, puede salirse con la suya con tan solo:
eval $(git config -f mytool.ini --list | tr . _)
# or if 'eval' skeeves you out excessively
source <(git config -f mytool.ini --list | tr . _)
que crea variables de entorno llamadas sectionname_variablename en el entorno actual. Esto, por supuesto, solo funciona si puede confiar en que ninguno de sus valores contendrá un punto o espacio en blanco (consulte a continuación para obtener una solución más sólida).
Otros ejemplos simples
Obteniendo valores arbitrarios, usando una función de shell para guardar la escritura:
function myini() { git config -f mytool.ini; }
Aquí también estaría bien un alias, pero normalmente no se expanden en un script de shell [ 1 ], y de todos modos los alias son reemplazados por las funciones de shell "para casi cualquier propósito", [ 2 ], según la página del manual de Bash .
myini --list
# result:
# section1.inputdir=~/some/dir
# section1.enablesomefeature=true
# section1.enablesomeotherfeature=yes
# section2.anothersetting=42
myini --get section1.inputdir
# result:
# ~/some/dir
Con la --typeopción, puede "canonizar" configuraciones específicas como enteros, booleanos o rutas (expandiéndose automáticamente ~):
myini --get --type=path section1.inputdir # value '~/some/dir'
# result:
# /home/myuser/some/dir
myini --get --type=bool section1.enablesomeotherfeature # value 'yes'
# result:
# true
Ejemplo un poco más robusto, rápido y sucio
Haga que todas las variables mytool.iniestén disponibles como SECTIONNAME_VARIABLENAMEen el entorno actual, conservando espacios en blanco internos en valores clave:
source <(
git config -f mytool.ini --list \
| sed 's/\([^.]*\)\.\(.*\)=\(.*\)/\U\1_\2\E="\3"/'
)
Lo que está haciendo la expresión sed, en inglés, es
- encontrar un montón de personajes que no sean de período hasta un período, recordando eso como
\1, luego
- encontrar un montón de caracteres hasta un signo igual, recordando eso como
\2, y
- encontrar todos los caracteres después del signo igual como
\3
- finalmente, en la cadena de reemplazo
- el nombre de la sección + el nombre de la variable está en mayúsculas y
- la parte del valor tiene comillas dobles, en caso de que contenga caracteres que tengan un significado especial para el shell si no están entre comillas (como espacios en blanco)
Las secuencias \Uy \Een la cadena de reemplazo (que en mayúscula esa parte de la cadena de reemplazo) son sedextensión GNU . En macOS y BSD, solo usaría múltiples-e expresiones para lograr el mismo efecto.
Tratar con comillas y espacios en blanco incrustados en los nombres de las secciones (lo que git configpermite) se deja como ejercicio para el lector.:)
Usar nombres de sección como claves en una matriz asociativa de Bash
Dado:
; foo.ini
[foobar]
session=foo
path=/some/path
[barfoo]
session=bar
path=/some/path
Esto producirá el resultado que solicita el OP, simplemente reorganizando algunas de las capturas en la expresión de reemplazo de sed, y funcionará bien sin GNU sed:
source <(
git config -f foo.ini --list \
| sed 's/\([^.]*\)\.\(.*\)=\(.*\)/declare -A \2["\1"]="\3"/'
)
Predigo que podría haber algunos desafíos al citar un .iniarchivo del mundo real , pero funciona para el ejemplo proporcionado. Resultado:
declare -p {session,path}
# result:
# declare -A session=([barfoo]="bar" [foobar]="foo" )
# declare -A path=([barfoo]="/some/path" [foobar]="/some/path" )