desarrollo-web-br-bd.com

¿Cómo configuro una variable de entorno en la línea de comando y hago que aparezca en los comandos?

Si corro

export TEST=foo
echo $TEST

Sale foo.

Si corro

TEST=foo echo $TEST

No es asi. ¿Cómo puedo obtener esta funcionalidad sin usar exportar o un script?

175
ashleysmithgpu

Esto se debe a que el Shell expande la variable en la línea de comando antes realmente ejecuta el comando y en ese momento la variable no existe. Si utiliza

TEST=foo; echo $TEST

funcionará.

export hará que la variable aparezca en el entorno de los comandos ejecutados posteriormente (para ver cómo funciona esto en bash, consulte help export). Si solo necesita que la variable aparezca en el entorno de un comando, use lo que ha intentado, es decir:

TEST=foo your-application
209
peterph

Sospecho que desea tener Shell variables para tener un alcance limitado, en lugar de variables de entorno. Las variables de entorno son una lista de cadenas que se pasan a los comandos cuando están ejecutados.

En

var=value echo whatever

Estás pasando el var=value cadena al entorno que recibe echo. Sin embargo, echo no hace nada con su lista de entorno¹ y de todos modos en la mayoría de los shells, echo está integrado y, por lo tanto, no ejecutado .

Si hubieras escrito

var=value sh -c 'echo "$var"'

Eso hubiera sido otro asunto. Aquí, estamos pasando var=value al comando sh, y sh utiliza su entorno. Los shells convierten cada una de las variables que reciben de su entorno en una variable Shell, por lo que la variable de entorno varsh recibe se convertirá en un $var variable, y cuando se expande en esa línea de comando echo, se convertirá en echo value. Como el entorno se hereda por defecto, echo también recibirá var=value en su entorno (o lo haría si se ejecutara), pero de nuevo, echo no se preocupa por el entorno.

Ahora, si sospecho que lo que quiere es limitar el alcance de las variables de Shell, hay varios enfoques posibles.

Portablemente (Bourne y POSIX):

(var=value; echo "1: $var"); echo "2: $var"

El (...) anterior inicia un sub-Shell (un nuevo proceso de Shell en la mayoría de los shells), por lo que cualquier variable declarada allí solo afectará a ese sub-Shell, por lo que esperaría que el código anterior arroje "1: valor" y "2:" o "2: whatever-var-was-set-to-before".

Con la mayoría de los shells tipo Bourne, puede usar funciones y el "local" incorporado:

f() {
  local var
  var=value
  echo "1: $var"
}
f
echo "2: $var"

Con zsh, puede usar funciones en línea:

(){ local var=value; echo "1: $var"; }; echo "2: $var"

o:

function { local var=value; echo "1: $var"; }; echo "2: $var"

Con bash y zsh (pero no ash, pdksh o AT&T ksh), este truco también funciona:

var=value eval 'echo "1: $var"'; echo "2: $var"

Una variante que funciona en algunos shells más (dash, mksh, yash) pero no zsh (a menos que en sh/ksh emulación):

var=value command eval 'echo "1: $var"'; echo "2: $var"

(el uso de command delante de un archivo incorporado especial (aquí eval) en los shells POSIX elimina su especialidad (aquí las asignaciones de variables de ellos permanecen vigentes después de que hayan regresado)


Ick Hablando estrictamente, eso no es completamente cierto. Varias implementaciones se preocuparán por las variables de entorno de localización (LANG, LOCPATH, LC_*...), la implementación GNU) se preocupa por el POSIXLY_CORRECT variable de entorno (comparar env echo --version con POSIXLY_CORRECT=1 env echo --version en un GNU).

43
Stéphane Chazelas

Lo estás haciendo correctamente, pero la sintaxis de bash es fácil de malinterpretar: podrías pensar que echo $TEST hace que echo recupere TEST env var luego lo imprime, no lo hace. Así dado

export TEST=123

entonces

TEST=456 echo $TEST

implica la siguiente secuencia:

  1. El Shell analiza la línea de comando completa y ejecuta todas las sustituciones variables, por lo que la línea de comando se convierte en

    TEST=456 echo 123
    
  2. Crea los vars temporales establecidos antes del comando, por lo que guarda el valor actual de TEST y lo sobrescribe con 456; la línea de comando es ahora

    echo 123
    
  3. Ejecuta el comando restante, que en este caso imprime 123 en stdout (por lo que el comando de Shell que queda ni siquiera usó el valor temporal de TEST)

  4. Restaura el valor de TEST

Utilice printenv en su lugar, ya que no implica la sustitución de variables:

>> export TEST=123
>> printenv TEST
123
>> TEST=456 printenv TEST
456
>> printenv TEST && TEST=456 printenv TEST && TEST=789 printenv TEST && printenv TEST
123
456
789
123
>>
10
Oliver

Puede hacer que esto funcione usando:

TEST=foo && echo $TEST
5
pradeepchhetri