texto sustituir script reemplazar para especiales comando caracteres buscar linux bash sed

linux - sustituir - sed shell



¿Cómo uso sed para cambiar mis archivos de configuración, con claves flexibles y valores? (6)

Quiero buscar un archivo de configuración para esta expresión: "central.database". Luego quiero cambiar la configuración asociada con "central.database" a "SQLTEST".

El diseño del archivo de configuración se vería así inicialmente:

central.database = SQLFIRSTTEST

Esto es lo que quiero que se vea después del reemplazo sed:

central.database = SQLTEST

Estoy haciendo esto en un script bash, ¡cualquier sugerencia, recomendación o solución alternativa es bienvenida!

(En realidad, tanto central.database como SQLTEST provienen de variables de bash aquí).

Mi código actual (tercer intento):

sshRetValue=$(ssh -p "35903" -i $HOME/sshids/idrsa-1.old ${1} <<EOF sed -i "s/^/($CENTRAL_DB_NAME/s*=/s*/).*/$//1$CENTRAL_DB_VALUE/" /home/testing.txt; echo $? EOF )

Mensaje de error:

Pseudo-terminal will not be allocated because stdin is not a terminal. sed: -e expression #1, char 58: unknown option to `s'' -bash: line 3: EOF: command not found


Aquí hay una expresión de ejemplo:

sed -i ''s/^/(central/.database/s*=/s*/).*$//1SQLTEST/'' file.cfg

Si quieres unir cosas con / en él, puedes usar otro delimitador:

sed -i ''s#^/(cent/ral/.data/base/s*=/s*/).*$#/1SQL/TEST#'' file.cfg

O con expansión variable:

VAL="SQLTEST" sed -i "s/^/(central/.database/s*=/s*/).*/$//1$VAL/" file.cfg

En tu ejemplo:

sshRetValue=`sed -i "s/^/(/1$CENTRAL_DB_NAME/s*=/s*/).*/$//1$CENTRAL_DB_VALUE/" /home/testing.txt`;

Hay un / 1 antes de $ CENTRAL_DB_NAME que no es válido. Además, sed no imprime su valor de retorno. Esta es la forma preferida de verificar los valores devueltos:

sed -i "s/^/($CENTRAL_DB_NAME/s*=/s*/).*/$//1$CENTRAL_DB_VALUE/" /home/testing.txt; sed_return_value=$?

Y, finalmente, canalizar a ssh (no probado):

sed_return_value=$(ssh server <<EOF sed -i "s/^/($CENTRAL_DB_NAME/s*=/s*/).*/$//1$CENTRAL_DB_VALUE/" /home/testing.txt; echo $? EOF )

El -i es para reemplazar datos en el archivo de entrada. De lo contrario, sed escribe en stdout.

Las expresiones regulares son un campo propio. Sería imposible explicarlos en profundidad en una respuesta de , a menos que haya alguna función específica que te elude.


Me gusta usar awk para esto, ya que es bastante fácil entender lo que está haciendo y se ocupa muy bien del separador ( = ) y también del hecho de que debe hacerse en una línea no comentada:

awk -v var="my_var" -v new_val="NEW VALUE" / # set the vars ''BEGIN{FS=OFS="="} # set separator to = match($1, "^//s*" var "//s*") { # check if it matches $2=" " new_val # if so, replace the line }1'' conf_file # print all lines

Esto usa match() para verificar si el patrón ocurre en cualquier línea dada. Si lo hace, realiza el reemplazo con el valor dado.

Por ejemplo:

$ cat conf hello my_var= SOME VALUE #my_var = ANOTHER VALUE bye

Cambiemos el valor en my_var a NEW VALUE :

$ awk -v var="my_var" -v new_val="NEW VALUE" ''BEGIN{FS=OFS="="}match($1, "^//s*" var "//s*") {$2=" " new_val}1'' conf hello my_var= NEW VALUE #my_var = ANOTHER VALUE bye

También es posible establecer los valores en variables de shell y luego usarlos con -v :

$ var="my_var" $ new_value="NEW VALUE" $ awk -v var="$var" -v new_val="$new_value" ''BEGIN{FS=OFS="="}match($1, "^//s*" var "//s*") {$2=" " new_val}1'' conf

Y, por supuesto, puede poner todo esto dentro de una función de shell que luego llama normalmente:

#!/bin/bash replace () { file=$1 var=$2 new_value=$3 awk -v var="$var" -v new_val="$new_value" ''BEGIN{FS=OFS="="}match($1, "^//s*" var "//s*") {$2=" " new_val}1'' "$file" } # Call the replace() function with the necessary parameters replace "conf" "my_var" "NEW VALUE"

Tras la ejecución, esto vuelve

hello my_var= NEW VALUE #my_var = ANOTHER VALUE bye

Si bien también puede hacer que el script reciba los parámetros de la siguiente manera: ./script.sh "conf_file" "var_to_replace" "NEW VALUE" para pasarlos a la función.


Sé que es demasiado tarde para agregar una respuesta a esta pregunta, sin embargo, pensé en compartir mi conocimiento con todos ustedes. Hay un enfoque muy general que he seguido para resolver un tipo similar de problema. He eliminado toda la línea que corresponde a la cadena y he añadido los valores necesarios a esa clave. A tu pregunta aquí está la respuesta

replaceValue=SQLTEST sed -i "/central.database =/d" /home/testing.txt echo "central.database = $replaceValue" >> /home/testing.txt

sed elimina la línea de cadena correspondiente del archivo y la siguiente línea inmediata inserta la clave y el valor requeridos en el archivo.


Si desea reemplazar entre 2 archivos de propiedades, puede usar esto:

awk -F= ''NR==FNR{A[$1]=$2;next}$1 in A{$2=A[$1]}1'' OFS=''/='' /tmp/masterfile /opt/props/finalfile.properties > /tmp/tmp.txt && mv -f /tmp/tmp.txt /opt/props/finalfile.properties


Usé este script para mantener las prioridades.

Los argumentos $ 1 tendrán una carpeta en la que existen varios archivos de configuración. $ 2 tendrán propiedades que deben ser reemplazadas en $ 1 ruta y sub paths archivos # 3 tendrán propiedades que necesitan ser reemplazadas por encima de $ 2

También tiene lógica oculta para verificar la existencia de variables de entorno para las claves existentes en $ 2 y $ 3 y dar prioridad a eso.

es decir, si existe una clave en el entorno que sería la más alta prioridad. Al lado de eso sería $ 3 y al lado de eso sería $ 1 archivo.

#!/bin/bash #Usage is propertyReplacer <CONFIG_FOLDER_PATH> <CONFIG_FILE_2ND_PRIORITY> <CONFIG_FILE_1ST_PRIORITY> function propertyReplacer() { filePathToAct="$1" propertiesFilePath="$2" propertiesSecureFilePath="$3" declare -A keyValues while IFS=''='' read -r key value; do if [ "$key" == "" ]; then continue elif [[ "$key" =~ ^#.*$ ]]; then continue else echo $key " --> " $value keyValues[$key]=$value fi done < "$propertiesFilePath" if [ ! -f "$propertiesSecureFilePath" ]; then continue else while IFS=''='' read -r key value; do if [ "$key" == "" ]; then continue elif [[ "$key" =~ ^#.*$ ]]; then continue else echo $key " --> " $value keyValues[$key]=$value fi done < "$propertiesSecureFilePath" fi for key in ${!keyValues[@]}; do envProp=${key//[@]/} if [ "$(eval echo ''$''$envProp)" == "" ]; then echo "Environment key not exist" $envProp else value=$(eval echo ''$''$envProp) echo "From Environment " $envProp " --> "$value keyValues[$key]=$value fi done find "$filePathToAct" | while read -r resultFileName; do if [ ! -f "$resultFileName" ]; then continue else echo "Acting on the file $resultFileName" for key in ${!keyValues[@]}; do value=$(echo "${keyValues[${key}]}" | sed ''s/////////g'') echo "sed -i ''s/$key/$value/g'' $resultFileName " eval "sed -i ''s/$key/$value/g'' $resultFileName " done fi done }


sed -i -e ''/central.database =/ s/= .*/= new_value/'' /path/to/file

Explicación:

  • -i le dice a sed que guarde los resultados en el archivo de entrada. Sin él sed imprimirá los resultados a stdout.
  • /central.database =/ coincide con las líneas que contienen la cadena entre barras, es decir, "central.database =".
  • La parte s/OLD/NEW/ realiza una sustitución. La secuencia VIEJA es una expresión regular para unir y la parte NEW es la cadena para sustituirla.
  • En expresiones regulares,. .* Significa "hacer coincidir cualquier cosa". Así que = .* Coincide con un signo igual, espacio y luego cualquier otra cosa después.