Edición del archivo de configuración a través de un script bash

9

He estado tratando de escribir un script bash simple que usaré para instalar una aplicación y actualizar su archivo de configuración. Estoy teniendo dificultades para modificar su archivo de configuración.

# DBHost=localhost
DBName=test
# DBPassword=

¿Alguna sugerencia de cómo puedo modificar la modificación de la siguiente manera?

DBHost=localhost
DBName=database
DBPassword=password
compixtr
fuente
No puedo creer que tengamos que escribir expresiones regulares propensas a errores solo para hacer esta tarea tan común. Realmente debería haber una herramienta estandarizada como "update_config test.confg -uncomment_if_pressent DBHost = localhost".
bigjosh

Respuestas:

3

La mejor manera depende de si espera que el archivo también sea modificado por humanos, qué tan complejo es el archivo y si desea que su script tenga prioridad si parece que alguien más quiere un valor diferente. Es decir, si el archivo ya contiene DBPassword=swordfish, ¿desea conservarlo o reemplazarlo DBPassword=password?

Una forma común de lidiar con esto es tener una sección del archivo delimitada por "comentarios mágicos", y solo editar la parte entre estos comentarios. Aquí hay una manera de hacer esto con awk. Si los comentarios mágicos no están presentes, la nueva sección se agrega al final del archivo. Advertencia: código no probado.

begin_marker='# BEGIN AUTOMATICALLY EDITED PART, DO NOT EDIT'
end_marker='# END AUTOMATICALLY EDITED PART'
new_section='DBHost=localhost
DBName=database
DBPassword=password'
export begin_marker end_marker
awk <file.conf >file.conf.new -v begin_marker="$begin_marker" -v begin_marker="$end_marker" -v new_section="$new_section" '
    1 {print}
    $0 == begin_marker && !changed {
        do {getline} while ($0 != end_marker); # discard old section content
        print new_section;
        print;
        changed = 1;
    }
    END {if (!changed) {print begin_marker; print new_section; print end_marker;}}
'
ln -f file.conf file.conf.old
mv -f file.conf.new file.conf

Este enfoque no funciona bien si el programa que lee el archivo de configuración no admite varias líneas que configuran el mismo elemento de configuración. En ese caso, realmente necesitará eliminar los viejos. En este caso, recomendaría dejar los comentarios intactos y agregar su propia configuración al final.

grep -vE '^[[:blank:]]*(DBHost|DBName|DBPassword)=$' <file.conf >file.conf.new
cat <<EOF >>file.conf.new
DBHost=localhost
DBName=database
DBPassword=password
EOF
ln -f file.conf file.conf.old
mv -f file.conf.new file.conf
Gilles 'SO- deja de ser malvado'
fuente
¿Probaste este código? o todavía no se ha probado?
rubo77
Otros buenos ejemplos aquí: stackoverflow.com/questions/5955548/…
rubo77
2

Si eso es todo lo que necesitas, podrías hacer algo como

sed  -i.bak -e 's/DBName=.*/DBName=database/' \
 -e 's/#* *DBHost=.*/DBHost=localhost/' \
 -e 's/#* *DBPassword=.*/DBPassword=password/' config.file

Esto copia del original config.filea config.file.baky hacer los cambios necesarios.

terdon
fuente
2

Iré con "ex" en modo silencioso:

ex -s $CONFIG_FILE << END_CMDS
%s/^#.DBHost/DBHOST/
%s/DBName=test/DBName=database/
%s/^#.DBPassword/DBPassword/
w!
q
END_CMDS

El sedcomando de terdon es compacto y eficiente. Pero la interacción de un "documento aquí" lleno de comandos ex e interpolación de cadenas de shell puede ser poderosa. Por ejemplo, la contraseña podría sustituirse como el valor de una variable de shell:

%s/^#.DBPassword=password/DBPassword=$PASSWORD/

Si usa vio vimy está familiarizado con el modo ':', agregar ediciones nuevas / mejores / diferentes también es bastante fácil.

Bruce Ediger
fuente
Si bien ex es poderoso, es difícil recuperarse de los errores (por ejemplo, cuando falta una línea esperada). Aquí puede escapar sin ningún comportamiento condicional, pero esto no se generaliza tan bien.
Gilles 'SO- deja de ser malvado'