573 Stimmen

Das Setzen einer Umgebungsvariablen vor einem Befehl in der Bash funktioniert nicht für den zweiten Befehl in einer Pipe

In einer bestimmten Shell würde ich normalerweise eine oder mehrere Variablen setzen und dann einen Befehl ausführen. Kürzlich lernte ich das Konzept kennen, eine Variablendefinition einem Befehl voranzustellen:

FOO=bar somecommand someargs

Das funktioniert... irgendwie. Es funktioniert nicht, wenn Sie eine LC_* Variable (die den Befehl zu beeinflussen scheint, aber no seine Argumente, zum Beispiel, [a-z] char-Bereiche) oder bei der Weiterleitung der Ausgabe an einen anderen Befehl so:

FOO=bar somecommand someargs | somecommand2  # somecommand2 is unaware of FOO

Ich kann somecommand2 vorangestellt FOO=bar was zwar funktioniert, aber unerwünschte Duplizierung hinzufügt, und es hilft nicht bei Argumenten, die abhängig von der Variable interpretiert werden (zum Beispiel, [a-z] ).

Wie kann man dies in einer einzigen Zeile tun?

Ich denke an etwas in der Größenordnung von:

FOO=bar (somecommand someargs | somecommand2)  # Doesn't actually work

Ich habe viele gute Antworten bekommen! Das Ziel ist es, dies in einem Einzeiler zu halten, vorzugsweise ohne die Verwendung von export . Die Methode mit einem Aufruf der Bash war insgesamt am besten, obwohl die Klammerversion mit export war er etwas kompakter. Die Methode der Umleitung anstelle eines Rohrs ist ebenfalls interessant.

489voto

Dennis Williamson Punkte 322329
FOO=bar bash -c 'somecommand someargs | somecommand2'

331voto

0xC0000022L Punkte 19207

Wie wäre es, die Variable zu exportieren, aber nur innerhalb der Subshell?

(export FOO=bar && somecommand someargs | somecommand2)

Keith einen Punkt hat, um die Befehle bedingungslos auszuführen, tun Sie dies:

(export FOO=bar; somecommand someargs | somecommand2)

79voto

benjimin Punkte 2950

Utilice env .

Zum Beispiel, env FOO=BAR command . Beachten Sie, dass die Umgebungsvariablen wiederhergestellt/geändert werden, wenn command beendet die Ausführung.

Seien Sie nur vorsichtig, was die Shell-Ersetzung angeht, d.h. wenn Sie auf $FOO explizit in der gleichen Befehlszeile eingeben, müssen Sie es eventuell mit einem Escapezeichen versehen, damit Ihr Shell-Interpreter die Ersetzung nicht vornimmt es läuft env .

$ export FOO=BAR
$ env FOO=FUBAR bash -c 'echo $FOO'
FUBAR
$ echo $FOO
BAR

62voto

gniourf_gniourf Punkte 41590

Sie können auch Folgendes verwenden eval :

FOO=bar eval 'somecommand someargs | somecommand2'

Da diese Antwort mit eval nicht allen zu gefallen scheint, möchte ich etwas klarstellen: wenn es so verwendet wird, wie es geschrieben steht, mit den einfachen Anführungszeichen ist es vollkommen sicher. Er ist gut, da er weder einen externen Prozess startet (wie die akzeptierte Antwort) noch die Befehle in einer zusätzlichen Subshell ausführt (wie die andere Antwort).

Da wir ein paar regelmäßige Aufrufe erhalten, ist es wahrscheinlich gut, eine Alternative zu eval das allen gefällt und alle Vorteile (und vielleicht sogar noch mehr!) dieses schnellen eval "Trick". Verwenden Sie einfach eine Funktion! Definieren Sie eine Funktion mit allen Ihren Befehlen:

mypipe() {
    somecommand someargs | somecommand2
}

und führen Sie es mit Ihren Umgebungsvariablen wie folgt aus:

FOO=bar mypipe

26voto

Akhil Punkte 773

Ein einfacher Ansatz ist die Verwendung von ;

Zum Beispiel:

ENV=prod; ansible-playbook -i inventories/$ENV --extra-vars "env=$ENV"  deauthorize_users.yml --check

command1; command2 führt den Befehl2 nach der Ausführung von Befehl1 aus, und zwar nacheinander. Dabei spielt es keine Rolle, ob die Befehle erfolgreich waren oder nicht.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X