Quiero que mi script lea un archivo que contenga pares clave / valor de variables de entorno para establecer, y luego establecerlas.
Hasta ahora, tengo esto:
#!/bin/bash
cat $1 | while read kv
do
key=${kv%=*}
val=`echo ${kv#*=} | sed 's/^"\|"$//g'`
export $key="$val"
done
Y quiero leer un archivo como este:
XAUTHLOCALHOSTNAME="localhost"
DISPLAY=":0"
XAUTHORITY="/tmp/some-XAuthority"
Solo necesito estas variables en el alcance durante la duración del script, por lo que no necesito resolver el problema de establecer una variable en el script para el alcance principal .
Según mis pruebas, creo que mi problema radica export $key="$val"
, así que creo que solo necesito un reemplazo para esa línea.
bash
shell-script
environment-variables
palswim
fuente
fuente
key=${kv%%=*}
es mejor quekey=${kv%=*}
porque %% y ## difieren de% y # para saber si la parte eliminada es la parte removible más corta o más largaRespuestas:
export $key=$val
debería funcionar bien enbash
. Sospecho que su problema es la tubería (|
). Todos los comandos en una tubería se ejecutan en una subshell. En su ejemplo, la instancia debash
eso está ejecutando su script bifurcará 2 subcapas: una paracat $1
y otra para elwhile read ...
. Las variables se asignan y exportan en la subshell que ejecuta el ciclo while, y luego todas ellas se desechan rápidamente cuando la subshell sale. Una forma de solucionar esto es no generar subcapas en absoluto. En lugar de un uso inútil de cat , intente la redirección en su lugar:BashFAQ 24 explica esto con mucho mayor detalle.
Un enfoque alternativo es simplemente obtener el archivo, con exportaciones incluidas:
El
<( )
es el proceso de sustitución.Como una nota adicional de precaución, dado que está leyendo variables de entorno de un argumento, debe asegurarse de que el archivo de argumentos
$1
sea una fuente confiable para que no pueda dañar su script.fuente
cat
. Pero, el script con redirección funciona ahora, ¡gracias!( jw013 ya ha dado una respuesta correcta , pero quiero señalar algunos problemas más).
El lado derecho de una tubería se ejecuta en su propio subshell en bash (así como la mayoría de los otros shells, con la excepción de ATT ksh y zsh). Entonces, está configurando las variables de entorno en el subshell que ejecuta el bucle, pero no en el proceso del shell principal.
Aquí hay una solución fácil que es reemplazar el uso inútil de
cat
una redirección:En general, si necesita preprocesar la entrada, coloque el bucle y el resto del script (al menos la parte que necesita las variables cambiadas) dentro de un bloque.
Tenga en cuenta que, en general,
while read line; do …
no itera sobre las líneas de entrada. Ver ¿Por qué sewhile IFS= read
usa con tanta frecuencia, en lugar deIFS=; while read..
? para una explicación El idioma correcto para iterar sobre las líneas de entrada esAquí, la eliminación de espacios en blanco iniciales y finales no importa, ya que no debería haber ninguna entrada de muestra dada, pero es posible que deba
-r
evitar la expansión de la barra invertida. Es posible quewhile read line
de hecho sea una forma correcta de leer su entrada (pero sospecho que solo si los valores de las variables no contienen nuevas líneas). También es posible que su formato de entrada sea ambiguo o más complejo de analizar. Verifique qué sucede si el valor de una de las variables contiene un carácter de nueva línea, una comilla doble o una barra diagonal inversa.Un punto en el que definitivamente está manipulando la entrada es cuando extrae el valor:
En primer lugar, es necesario utilizar comillas dobles alrededor de la sustitución de variables:
echo "${kv#*=}"
; de lo contrario, el shell realiza la división de palabras y la generación de nombre de archivo (es decir, globalización) en él. En segundo lugar,echo
no es una forma confiable de imprimir una cadena, porque algunas cadenas que comienzan con a-
se tratan como opciones, y algunos shells realizan una expansión de barra invertida en el argumento. Una forma confiable y portátil de imprimir una cadena esprintf %s "${kv#*=}"
. Además, si el valor abarca varias líneas, el programa sed actuará en cada una por separado, lo cual es incorrecto. Esto se puede arreglar, pero no hay un método más fácil, que es el uso de las instalaciones de manipulación de cadenas de la shell:val=${kv#*=}; val=${val#\"}; val=${val%\"}
.Suponiendo que su entrada se analiza correctamente con un plano
read
, aquí hay una manera más simple de analizarla, aprovechando laIFS
configuración para dividir cada línea:fuente
Otra buena opción podría ser colocarlo
export
en el archivo y obtenerlo:y entonces:
fuente
/ env
guión
fuente