¿Cómo sustituyo las variables de entorno cuando salgo de un archivo?

6

Me gustaría escupir de alguna manera un archivo (que tiene referencias de variables env) y sustituir los valores reales. Esto es lo que he intentado, pero como puede ver, no funciona. ¿Algunas ideas?

-bash-3.00$ cat vars_file 
${MY_VAR}
-bash-3.00$ export MY_VAR=MY_VALUE; cat ./vars_file | xargs echo
${MY_VAR}
andersonbd1
fuente

Respuestas:

9

Hilo antiguo, pero este es un problema recurrente. Aquí hay una solución usando bash mapfile:

mateus@mateus:/tmp$ cat input.txt
a = $a
b = $b
mateus@mateus:/tmp$ echo a=$a, b=$b
a=1, b=2
mateus@mateus:/tmp$ function subst() { eval echo -E "$2"; }
mateus@mateus:/tmp$ mapfile -c 1 -C subst < input.txt
a = 1
b = 2

Bash builtin mapfilellama a la función definida por el usuario subst(consulte las opciones -C / -c) en cada línea leída del archivo de entrada input.txt. Dado que la línea contiene texto no escapado, evalse utiliza para evaluarlo y echoel texto transformado en stdout (-E evita que se interpreten caracteres especiales).

En mi humilde opinión, esta es una solución mucho más elegante que cualquier solución basada en sed / awk / perl / regex.

Otra posible solución es usar la propia sustitución de shell. Esto parece una forma más "portátil" que no se transmite en mapfile:

mateus@mateus:/tmp$ EOF=EOF_$RANDOM; eval echo "\"$(cat <<$EOF
$(<input.txt)
$EOF
)\""
a = 1
b = 2

Tenga en cuenta que usamos $EOFpara minimizar el documento here-conflict de cat con contenido input.txt

Ambos ejemplos de: https://gist.github.com/4288846

EDITAR: Lo sentimos, el primer ejemplo no maneja los comentarios y el espacio en blanco correctamente. Trabajaré en eso y publicaré una solución. EDIT2: Fix double $ RANDOM eval

caruccio
fuente
¿Has probado tu segunda solución? ¿Cada referencia no $RANDOMgenerará números posiblemente diferentes? Cuando escribo echo $RANDOM $RANDOMen una terminal, obtengo dos números diferentes.
Victor
Tienes razón. Produce 2 números aleatorios y ese heredoc nunca se cerrará. Lo editaré para arreglarlo. ¡Gracias!
caruccio
2

Se puede hacer con script (por ejemplo, el nombre del archivo es expand.sh):

while read line; do eval echo \"$line\"; done < $1 > $2

El guión puede llamarse así:

env VAR1=value1 sh expand.sh input_file output_file

- http://www.issociate.de/board/post/281806/sed_replace_by_enviroment_var_content.html

Tamara Wijsman
fuente
¿Alguna idea de cómo hacer esto cuando hay un par en el archivo? -bash: error de sintaxis cerca de token inesperado `('
andersonbd1
@ andersonbd1: Supongo que podría reemplazar los paréntesis con sed y reemplazarlos más tarde. De lo contrario, es posible que desee eliminar la marca de aceptación de mi respuesta para obtener una mejor solución awk, ya que las preguntas anteriores mencionan que no puede leer el efecto con sed.
Tamara Wijsman
1
Supongo que sed es mi mejor apuesta. No es bonito pero funcionará. Gracias TomWij
andersonbd1
Es posible que desee citar esa variable: echo "$line". @ andersonbd1: ¿cuál es el contexto de los paréntesis?
Dennis Williamson
1
Vaya, lo siento, olvidé decirte que también deberías usar read -r.
Dennis Williamson
1

Aquí está mi solución propuesta:

eval $'cat <<\002\n'"$(<ifile)"$'\n\002' > ofile

\002se puede reemplazar con cualquier carácter o cadena que no ocurra en el archivo. Para eliminar cualquier aparición del carácter delimitador en el archivo de entrada:

eval $'cat <<\002\n'"$(tr -d '\002' < ifile)"$'\n\002' > ofile

Esta solución parece resolver la mayoría de los problemas, pero es notablemente vulnerable a la inyección de comandos en el archivo de plantilla a través de $(command)directivas.

Stefan Farestam
fuente
1

$"xxx" puede ser una manera fácil

a=$(< file)
eval b=\$\"$a\"

entonces "$ b" es el texto expandido

a B C
fuente
0

Esto define una función de shell que usa python para imitar la expansión de shell básica de las variables $ {name}. Lo uso para expandir las variables bash incrustadas en los scripts sql. Dado que mi archivo no es un verdadero archivo bash, no puede usar el incorporado eval () bash

apply_shell_expansion() {
python - << EOF
import os
doc=open('${1}').read()
for k,v in os.environ.items():
  doc = doc.replace('$'+'{'+k+'}',v)
print doc
EOF
}
MARK L HAMMINGH
fuente
1
(1) ¿Qué hacer myvary myvaluequé hacer con algo? (2) No necesitas decirlo ${1}; se puede decir $1.
Scott
eliminó el ejemplo myvar = myvalue porque aparentemente es más confuso que útil
MARK L HAMMINGH