`env foo = bar echo $ foo` não imprime nada

8

Eu acho que estou tendo um enorme peido cerebral. eu esperaria

env foo=bar echo $foo

... para imprimir bar, mas recebo uma linha vazia. Wat.

O mesmo acontece se eu usar a sintaxe do bash:

foo=bar echo $foo
badp
fonte

Respostas:

8

Uma pergunta semelhante foi respondida recentemente : os símbolos são avaliados na linha antes que o símbolo seja definido nesta linha, tornando necessário dividir a definição e o uso dos símbolos para separar as linhas.

Solicitado por um comentário, você poderia ter feito isso:

foo=bar bash -c 'echo $foo'

que primeiro atribui um valor fooe o passa para um novo processo como uma variável de ambiente onde pode ser impresso.

Você pode ler mais sobre isso no reconhecimento do POSIX Shell Command Language Token .

Seguindo o comentário do @mikeserv :

  • O POSIX não é explícito o suficiente para fornecer a resposta completa.
  • No início da seção citada, diz

    O shell deve ler sua entrada em termos de linhas de um arquivo, de um terminal no caso de um shell interativo ou de uma string no caso de sh -c ou system ().

  • no final, diz

    Depois que um token é delimitado, ele é categorizado conforme exigido pela gramática na Gramática do Shell.

  • mas o POSIX não diz explicitamente que toda a linha é tokenizada antes de trabalhar na gramática.
  • nesse caso, contamos com a prática existente - o shell está em conformidade porque nada contradiz o padrão escrito, mas o padrão não pode ser usado para prever o comportamento em todos os casos.
  • o mesmo comentário se aplica, é claro, ao comportamento dos pseudônimos (razão pela qual me referi a ele como uma pergunta semelhante ).
Thomas Dickey
fonte
ou se você está bem com citando o inferno,env foo=bar bash -c 'echo $foo'
badp
Na verdade, a questão do alias se baseia na implicação da seção de reconhecimento de token de que os tokens são todos computados para uma determinada linha antes de passar para a gramática. Mas, para ambos, o padrão não é explícito , fazendo você confiar na prática existente.
Thomas Dickey
@ thomasdickey - sim, essa era minha essência também. quando você escreve um comentário, se você @username...commentespecificar o usuário especificado, receberá uma pequena mensagem informando que você estava conversando com ele. bem, eles serão relevantes para o segmento.
mikeserv
@mikeserv (assim). hmm - vou ter isso em mente (apesar de como ele funciona com espaços em branco incorporados não era aparente).
Thomas Dickey
Curtiu isso. tangencialmente, eu tinha uma olhada luit.ce eu acho que eu posso apenas mudar setup_io(){ ... ;fnctl(0, [GS]ETFL, 0);...}a fazer 2para o primeiro argumento. bem, acho que as funções copyTermios()e setRawTermios()também precisam de uma pequena modificação, mas acho que deve ser simples. o rc = (return)para cada linha parece estranho - mas também não sou programador de C. isso é coisa sua ou foi herdada? e se o comentário dos espaços em branco se referir a "${set_null_var:=new val and $(echo other stuff)}"você, você estará praticamente seguro com qualquer coisa. algumas conchas fazem coisas estranhas }.
mikeserv