with variable another bash replace sed awk textutils

bash - variable - Rellenar marcadores de posición en el archivo en un solo pase



sed replace a string with another (5)

Tengo un archivo de texto esqueleto con cadenas de marcador de posición:

blah blah blah blah $PLACEHOLDER_1$ blah $PLACEHOLDER_2$

y así. La "forma" específica de marcadores de posición no importa; puedo cambiarlos a lo que sea más cómodo para una implementación específica.

Tengo un script bash donde conozco los valores de los marcadores de posición, y necesito generar un nuevo archivo, con marcadores de posición reemplazados por valores.

#! /bin/sh PLACEHOLDER_1 = ''string 1'' PLACEHOLDER_2 = ''multiline string 2'' # TODO: Generate file output.txt from file output.template # using placeholders above.

Puedo hacer esto en pases múltiples con sed, pero no es divertido. No quiero usar Perl. Quiero usar textutils y bash solo.

¿Cuál es la mejor manera de hacer lo que quiero en una sola pasada?


Sobre la base de la respuesta anterior, ¿tal vez usar una matriz y calcular la cadena sed?

#!/bin/sh PLACEHOLDER[0]=''string 1'' PLACEHOLDER[1]=''multiline string 2'' s="sed -i " for(( i=0 ; i<${#PLACEHOLDER[*]} ; i++ )) ; do echo ${PLACEHOLDER[$i]} s=$s"s/PLACEHOLDER_$i/${PLACEHOLDER[$i]}/g;" done echo $s

Sin embargo, parece fallar en las cadenas de varias líneas.

No sé qué tan portátiles pueden ser las matrices de Bash. Por encima del fragmento probado con "GNU bash, versión 3.2.17 (1) -release (i386-apple-darwin9.0)"


Todavía puede usar sed para hacer el reemplazo en una sola pasada. Solo necesita especificar todos los reemplazos en un comando.

p.ej.

sed -i ''s/PLACEHOLDER_1/string 1/g;s/PLACEHOLDER_2/string 2/g'' <file>


Aquí hay una manera de hacerlo sin sed:

Primero, un archivo de plantilla ligeramente modificado en el que los marcadores de posición son variables de bash:

blah blah blah blah $PLACEHOLDER_1 blah $PLACEHOLDER_2

Y el guion:

#! /bin/sh templatefile=output.template outputfile=output.txt PLACEHOLDER_1=''string 1'' PLACEHOLDER_2=''multiline string 2'' # DONE: Generate file output.txt from file output.template # using placeholders above. echo "$(eval "echo /"$(cat $templatefile)/"")" > $outputfile

Aquí hay una versión que muestra una plantilla contenida en el script, pero con un giro. También muestra los valores predeterminados, que también se pueden usar en la versión del archivo de plantilla, además de que puede hacer cálculos matemáticos en la plantilla:

#! /bin/sh template=''blah blah blah blah $PLACEHOLDER_1 blah ${PLACEHOLDER_2:-"some text"} blah ${PLACEHOLDER_3:-"some lines of text"} and the total is: $((${VAL_1:-0} + ${VAL_2:-0}))'' # default operands to zero (or 1) to prevent errors due to unset variables outputfile=output.txt # gears spin, bells ding, values for placeholders are computed PLACEHOLDER_1=''string 1'' PLACEHOLDER_2=''multiline string 2'' VAL_1=2 VAL_2=4 unset PLACEHOLDER_3 # so we can trigger one of the defaults # Generate file output.txt from variable $template # using placeholders above. echo "$(eval "echo /"$template/"")" > $outputfile

No sed, no loops, solo anidamiento peludo y citas. Estoy bastante seguro de que todas las citas lo protegerán de cosas maliciosas en un archivo de plantilla, pero no voy a garantizarlo.


Mi única solución bash:

TEMPLATE='' foo $var1 bar $var2'' eval "echo /"$TEMPLATE/""


Acabo de tropezar con esta pregunta porque estaba buscando exactamente lo mismo, y encontré envsubst(1) .

Puede usar envsubst si no le molesta usar variables de entorno:

PLACEHOLDER_1=''string 1'' PLACEHOLDER_2=''multiline string 2'' envsubst < output.template

Si tiene muchas variables, puede almacenarlas en un archivo y simplemente source (¡recuerde usar export al final del archivo de origen!)