( 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:
while read …; do …; done <"$1"
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.
grep '^foo_' "$1" | {
while read …; do …; done
do_something
}
Tenga en cuenta que, en general, while read line; do …
no itera sobre las líneas de entrada. Ver ¿Por qué se while IFS= read
usa con tanta frecuencia, en lugar de IFS=; while read..
? para una explicación El idioma correcto para iterar sobre las líneas de entrada es
while IFS= read -r line; do …
Aquí, 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 que while 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:
val=`echo ${kv#*=} | sed 's/^"\|"$//g'`
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 es printf %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 la IFS
configuración para dividir cada línea:
while read name value; do
value=${value#\"}; value=${value%\"}
export name="$value"
done <"$1"
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 larga