Acabo de encontrar varias respuestas, como analizar un archivo de texto delimitado ... que usa la construcción:
while IFS=, read xx yy zz;do
echo $xx $yy $zz
done < input_file
donde la IFS
variable se establece antes del read
comando.
He estado leyendo la referencia de bash pero no puedo entender por qué esto es legal.
Lo intenté
$ x="once upon" y="a time" echo $x $y
desde el símbolo del sistema bash pero no se hizo eco de nada. ¿Alguien puede señalarme dónde se define esa sintaxis en la referencia que permite que la variable IFS se establezca de esa manera? ¿Es un caso especial o puedo hacer algo similar con otras variables?
bash
shell
environment-variables
Mike Lippert
fuente
fuente
Respuestas:
Está debajo de Shell Grammar, Comandos simples (énfasis agregado):
Para que pueda pasar cualquier variable que desee. Su
echo
ejemplo no funciona porque las variables se pasan al comando, no se establecen en el shell. El shell se expande$x
y$y
antes de invocar el comando. Esto funciona, por ejemplo:fuente
man bash
en mi sistema ...Las variables definidas se convierten en variables de entorno en el proceso bifurcado.
Si tu corres
entonces golpear primero se expande
$A
en""
y a continuación, ejecutaAquí está la forma correcta:
Observe las comillas simples
bash -c
, de lo contrario tiene el mismo problema que el anterior.Entonces, su ejemplo de bucle es legal porque el comando bash 'read' incorporado buscará IFS en sus variables de entorno y buscará
,
. Por lo tanto,imprimirá
TEST is and I is test
Por último, en cuanto a la sintaxis, en un bucle for se espera una cadena. Por lo tanto, tuve que usar backticks para convertirlo en un comando. Sin embargo, los bucles while esperan una sintaxis de comando, como
IFS=, read xx yy zz
.fuente
A
variable no establecida bash se expande$A
a una cadena vacía, pero para evitar confusiones no usaría""
porque el código no es equivalente aA="b" echo ""
. No habrá argumento paraecho
.man bash
Las variables se expanden antes de que tenga lugar la asignación de variables. Por la razón obvia, eso
var=x
también funcionaría a la inversa, perovar=$othervar
no lo haría. Es decir,$x
se necesita antes de que esté disponible. Pero ese no es el problema principal. El principal problema es que la línea de comandos solo puede ser modificada por el entorno de shell, pero la asignación no se convierte en parte del entorno de shell.Combina características: desea un reemplazo de la línea de comandos pero coloca la definición de la variable en el entorno de comandos. Los reemplazos de la línea de comando deben ser realizados por el shell. El entorno debe ser explícitamente utilizado por el comando llamado. Si y cómo se hace esto depende del comando.
La ventaja de este uso es que puede configurar el entorno para un subproceso sin afectar el entorno del shell.
funciona como se espera porque en ese caso ambas características se combinan: el reemplazo de la línea de comandos no se realiza mediante el shell de llamada sino mediante el shell de subproceso.
fuente
x="once upon" y="a time" eval 'echo $x $y'
cuando no hay ningún subproceso involucrado, ya queeval
es un incorporado. Supongo que la cita relevante de la página de manual esThe environment for any simple command or function may be augmented temporarily by prefixing it with parameter assignments
. Teniendo en cuenta el ejemplo de la pregunta, tiene que ser así, yaread
que también es una función incorporada y funciona con un estado de cambio temporalIFS
.El comando que proporcione es diferente porque
$x
y$y
se expanden antes de lasecho
carreras de mando, por lo que sus valores de la corriente se utilizan cáscara, no los valores queecho
se ven en su entorno si fuera a buscar.fuente
x
yy
son para el entorno que seecho
ejecuta, no para el entorno en el queecho
se expanden los argumentos . ParaIFS=, read xx yy zz
, toda la cadena se lee, sin dividir, por elread
comando. Entonces , esa cadena se divide de acuerdo con el valor deIFS
, con las piezas correspondientes asignados axx
,yy
, yzz
.bash
primero analiza la línea de comando dada, reconoce que hay dos asignaciones de variables para aplicar al entorno del comando que viene, identifica el comando a ejecutar (echo
), expande los parámetros encontrados en los argumentos, luego ejecuta el comandoecho
con los argumentos expandidos.echo
no estaba seguro si podía "ver" la variable, ya que es un comando incorporado y, por lo tanto, no se ejecuta en una subshell que podría tener su propio entorno. Pero lo probé con eleval
que también está incorporado y de hecho lo sabe. Por ejemplo, pruebe loa=xyz eval 'echo $BASHPID $a; grep -z ^a /proc/$BASHPID/{,task/*}/environ'; echo $BASHPID $a
que muestra quea
solo se establece dentroeval
aunque el pid sea el mismo y el entorno no se altere durante la evaluación. (Para acceder/proc
necesitas ejecutar esto bajo Linux.) Parece que bash hace algo de magia adicional aquí.Voy por la imagen más grande de " por qué es legal"
Respuesta: Para que pueda llamar o invocar un programa y para esa invocación solo use una variable con una variable en particular.
Como ejemplo: tiene un parámetro para una conexión de base de datos llamado 'db_connection', y normalmente pasa 'test' como nombre para su conexión de base de datos de prueba. De hecho, incluso puede establecerlo como un valor predeterminado que no necesita pasar explícitamente. A veces, sin embargo, desea trabajar con la base de datos ci. Entonces, pasa el parámetro como 'ci' y luego el programa que se llama utiliza ese parámetro de la base de datos como el nombre de la base de datos que se usará para todas las llamadas a la base de datos. Para la próxima ejecución, si no repite el enfoque y simplemente llama al programa, la variable volverá a su valor predeterminado anterior.
fuente
También puedes usar
;
. Se evaluará antes porque es un separador de comandos.fuente