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 config
como 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 .ini
y 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 --type
opció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.ini
estén disponibles como SECTIONNAME_VARIABLENAME
en 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 \U
y \E
en la cadena de reemplazo (que en mayúscula esa parte de la cadena de reemplazo) son sed
extensió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 config
permite) 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 .ini
archivo 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" )