Normalmente, es posible establecer una variable de entorno para un comando con el prefijo así:
hello=hi bash -c 'echo $hello'
También sé que podemos usar una variable para sustituir cualquier parte de una invocación de comando como la siguiente:
$ cmd=bash
$ $cmd -c "echo hi" # equivalent to bash -c "echo hi"
Me sorprendió mucho descubrir que no se puede usar una variable para prefijar un comando para establecer una variable de entorno. Caso de prueba:
$ prefix=hello=hi
$ echo $prefix # prints hello=hi
$ $prefix bash -c 'echo $hello'
hello=hi: command not found
¿Por qué no puedo establecer la variable de entorno usando una variable? ¿La parte del prefijo es una parte especial? Pude hacerlo funcionar usando eval en frente, pero todavía no entiendo por qué. Estoy usando bash 4.4.
bash
environment-variables
variable
wbkang
fuente
fuente
env
lugar deeval
cuál IIRC es más seguro, pero más lento.Respuestas:
Sospecho que esta es la parte de la secuencia que te está atrapando:
Eso es del manual de referencia de Bash en la sección sobre Expansión de comandos simples.
En el
cmd=bash
ejemplo, no se establecen variables de entorno, y bash procesa la línea de comandos a través de la expansión de parámetros, dejandobash -c "echo hi"
.En el
prefix=hello=hi
ejemplo, nuevamente no hay asignaciones variables en la primera pasada, por lo que el procesamiento continúa con la expansión de parámetros, lo que resulta en una primera palabra dehello=hi
.Una vez que se han procesado las asignaciones de variables, no se vuelven a procesar durante la ejecución del comando.
Vea el procesamiento y sus resultados en
set -x
:Para una variación más segura de "expansión variable" -como- "variables de entorno" que
eval
, considere la sugerencia de wjandrea deenv
:No es estrictamente una asignación de variable de línea de comandos, ya que estamos utilizando la
env
función principal de la utilidad de asignar variables de entorno a un comando, pero cumple el mismo objetivo. La$prefix
variable se expande durante el procesamiento de la línea de comandos, proporcionando el nombre = valor aenv
quién se la pasabash
.fuente
$foo=bar bash -c ...
no funcionará, porque$foo=bar
no es una asignación variable (cualquiera que sea el valor de$foo
), porque$foo=bar
no se ajusta alname=value
patrón para la asignación variable.Porque
$prefix
no es una tarea. @Jeff tiene la explicación más larga .En su lugar, podría hacer algo similar con una función:
... e incluso puedes apilarlos, si quieres:
fuente