`env foo = bar echo $ foo` druckt nichts

8

Ich glaube, ich habe einen massiven Brainfart. Ich würde erwarten

env foo=bar echo $foo

... zum Drucken bar, aber ich bekomme stattdessen eine leere Zeile. Wat.

Das gleiche passiert, wenn ich die Bash-Syntax verwende:

foo=bar echo $foo
badp
quelle

Antworten:

8

Eine ähnliche Frage wurde kürzlich beantwortet : Die Symbole werden in der Zeile ausgewertet, bevor das Symbol in dieser Zeile definiert wird, sodass die Definition und Verwendung der Symbole zum Trennen von Zeilen aufgeteilt werden muss.

Auf Aufforderung durch einen Kommentar hätten Sie dies tun können:

foo=bar bash -c 'echo $foo'

Dieser weist zuerst einen Wert zu foound übergibt diesen als Umgebungsvariable an einen neuen Prozess, wo er gedruckt werden kann.

Weitere Informationen finden Sie in der POSIX Shell Command Language Token-Erkennung .

Nach dem Kommentar von @mikeserv :

  • POSIX ist nicht explizit genug, um die gesamte Antwort zu geben.
  • Am Anfang des zitierten Abschnitts steht

    Die Shell liest ihre Eingabe in Zeilen aus einer Datei, von einem Terminal bei einer interaktiven Shell oder von einer Zeichenfolge bei sh-c oder system ().

  • am Ende heißt es

    Sobald ein Token abgegrenzt ist, wird es gemäß den Anforderungen der Grammatik in der Shell-Grammatik kategorisiert.

  • POSIX sagt jedoch nicht explizit, dass die gesamte Zeile vor der Arbeit an der Grammatik mit einem Token versehen wird.
  • In diesem Fall stützen wir uns auf die bestehende Praxis - die Shell entspricht, weil nichts dem schriftlichen Standard widerspricht, aber der Standard kann nicht in allen Fällen zur Vorhersage des Verhaltens verwendet werden.
  • Der gleiche Kommentar gilt natürlich für das Verhalten von Aliasen (weshalb ich es als ähnliche Frage bezeichnet habe).
Thomas Dickey
quelle
oder wenn Sie mit dem Zitieren der Hölle env foo=bar bash -c 'echo $foo'
einverstanden
Tatsächlich beruht die Alias-Frage auf der Implikation des Token-Erkennungsabschnitts, dass alle Token für eine bestimmte Zeile berechnet werden, bevor zur Grammatik übergegangen wird. Für beide ist der Standard jedoch nicht explizit , sodass Sie sich auf die vorhandene Praxis verlassen können.
Thomas Dickey
@ Thomasdickey - Ja, das war auch mein Kern. Sie wissen, wenn Sie einen Kommentar schreiben @username...comment, wird der von Ihnen angegebene Benutzer eine kleine Nachricht erhalten, die ihn darüber informiert, dass Sie mit ihm gesprochen haben. Nun, sie werden, wenn es Thread-relevant ist.
Mikeserv
@mikeserv (so). hmm - das werde ich mir merken (obwohl nicht klar war, wie es mit eingebetteten Leerzeichen funktioniert).
Thomas Dickey
so wie das. Tangential habe luit.cich mir das angeschaut und ich denke, ich kann es einfach ändern setup_io(){ ... ;fnctl(0, [GS]ETFL, 0);...}, um es 2für das erste Argument zu tun . Nun, ich denke, die copyTermios()und setRawTermios()Funktionen müssen möglicherweise auch ein wenig modifiziert werden, aber es sollte einfach sein, denke ich. Das rc = (return)für jede Zeile scheint seltsam - aber ich bin auch kein C-Programmierer. Ist das dein Ding oder wurde das geerbt? und wenn sich Ihr Kommentar auf Leerzeichen bezieht, sind "${set_null_var:=new val and $(echo other stuff)}"Sie mit allem größtenteils sicher. Einige Muscheln machen seltsame Sachen mit }.
Mikeserv