Tengo varios archivos de texto en los que he introducido variables de shell ($ VAR1 o $ VAR2, por ejemplo).
Me gustaría tomar esos archivos (uno por uno) y guardarlos en archivos nuevos donde todas las variables habrían sido reemplazadas.
Para hacer esto, utilicé el siguiente script de shell (que se encuentra en StackOverflow):
while read line
do
eval echo "$line" >> destination.txt
done < "source.txt"
Esto funciona muy bien en archivos muy básicos.
Pero en archivos más complejos, el comando "eval" hace demasiado:
Las líneas que comienzan con "#" se omiten
El análisis de archivos XML da como resultado toneladas de errores
Hay una mejor manera de hacerlo? (en el script de shell ... sé que esto se hace fácilmente con Ant, por ejemplo)
Saludos cordiales
envsubst
es parte de GNU gettextsource.txt
contiene$
caracteres fuera de la expansión variable,envsubst
también los reemplazará y no hay forma de escapar del$
. La solución común (fea) esexport DOLLAR="$"
.En referencia a la respuesta 2, al hablar de envsubst, preguntaste:
La respuesta es que simplemente necesita exportar sus variables antes de llamar
envsubst
.También puede limitar las cadenas de variables que desea reemplazar en la entrada usando el
envsubst
SHELL_FORMAT
argumento (evitando el reemplazo involuntario de una cadena en la entrada con un valor de variable de shell común, por ejemplo$HOME
).Por ejemplo:
export VAR1='somevalue' VAR2='someothervalue' MYVARS='$VAR1:$VAR2' envsubst "$MYVARS" <source.txt >destination.txt
Reemplazará todas las instancias de
$VAR1
y$VAR2
(y soloVAR1
yVAR2
) ensource.txt
con'somevalue'
y'someothervalue'
respectivamente.fuente
'
que se utilizan para establecerMYVARS
son crucialesexport
,envsubst
o cualquier comando de entrelazado puede fallar cuando el texto a sustituir es grande. Referencia.SHELL_FORMAT
argumento (es decir"$MYVARS"
) hace que todas las variables exportadas sean sustituidas. Si eso es lo que necesita, no se preocupe.Sé que este tema es antiguo, pero tengo una solución de trabajo más simple sin exportar las variables. Puede ser un delineador, pero prefiero dividir usando
\
el final de la línea.var1='myVar1'\ var2=2\ var3=${var1}\ envsubst '$var1,$var3' < "source.txt" > "destination.txt" # ^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^ # define which to replace input output
Las variables deben definirse en la misma línea que
envsubst
para ser consideradas como variables de entorno.El
'$var1,$var3'
es opcional para reemplazar solo los especificados. Imagínese un archivo de entrada${VARIABLE_USED_BY_JENKINS}
que no debería ser reemplazado.fuente
$ export MY_ENV_VAR=congratulation
$MY_ENV_VAR
También puede usar todas las demás variables ENV definidas por su sistema como (en linux) $ TERM, $ SHELL, $ HOME ...
$ envsubst "`printf '${%s} ' $(sh -c "env|cut -d'=' -f1")`" < in.txt > out.txt
y debería ver "felicitaciones".
fuente
Si realmente solo desea usar bash (y sed), entonces revisaría cada una de sus variables de entorno (como las devuelve
set
en modo posix) y construiría un montón de-e 'regex'
for sed a partir de eso, terminado por a-e 's/\$[a-zA-Z_][a-zA-Z0-9_]*//g'
, luego pasaría todo eso a sed.Sin embargo, Perl haría un mejor trabajo, tiene acceso a las variables de entorno como una matriz y puede hacer reemplazos ejecutables para que solo coincida con cualquier variable de entorno una vez.
fuente
perl -pi -e 'foreach $key(sort keys %ENV){ s/\$$key/$ENV{$key}/g}' "$main_tf_file"
En realidad, debe cambiar su
read
a,read -r
lo que hará que ignore las barras invertidas.Además, debe escapar de las comillas y las barras invertidas. Entonces
while read -r line; do line="${line//\\/\\\\}" line="${line//\"/\\\"}" line="${line//\`/\\\`}" eval echo "\"$line\"" done > destination.txt < source.txt
Sin embargo, sigue siendo una forma terrible de hacer expansión.
fuente
Exporte todas las variables necesarias y luego use un Perl Onliner
TEXT=$(echo "$TEXT"|perl -wpne 's#\${?(\w+)}?# $ENV{$1} // $& #ge;')
Esto reemplazará todas las variables ENV presentes en TEXT con valores reales. Las citas también se conservan :)
fuente
Si desea que las variables env se reemplacen en sus archivos de origen mientras mantiene todas las variables que no son env como están, puede usar el siguiente comando:
envsubst "$(printf '${%s} ' $(env | sed 's/=.*//'))" < source.txt > destination.txt
Aquí se explica la sintaxis para reemplazar solo variables específicas . El comando anterior usa un sub-shell para listar todas las variables definidas y luego pasarlo al
envsubst
Entonces, si hay una variable env definida llamada
$NAME
, y susource.txt
archivo se ve así:Hello $NAME Your balance is 123 ($USD)
El
destination.txt
será:Hello Arik Your balance is 123 ($USD)
Observe que
$NAME
se reemplaza y$USD
se deja intactofuente
Llame al binario de perl, en el modo de búsqueda y reemplazo por línea (the
-pi
) ejecutando el código perl (the-e
) entre comillas simples, que itera sobre las claves del%ENV
hash especial que contiene los nombres de las variables exportadas como claves y los valores de las variables exportadas como los valores de las claves y para cada iteración simple reemplace una cadena que contenga un$<<key>>
con su<<value>>
.perl -pi -e 'foreach $key(sort keys %ENV){ s/\$$key/$ENV{$key}/g}' file
Advertencia: se requiere un manejo lógico adicional para los casos en los que dos o más vars comienzan con la misma cadena ...
fuente
envsubst
parece exactamente algo que quería usar, pero la-v
opción me sorprendió un poco.Si
envsubst < template.txt
bien funcionaba bien, lo mismo con la opción-v
no funcionaba:Como escribí, esto no estaba funcionando:
Tuve que hacer esto para que funcione:
Quizás ayude a alguien.
fuente