it-swarm.com.de

Bash: Weisen Sie die Ausgabe der Pipe einer Variablen zu

Ich versuche, die Ausgabe einer Pipe in eine Variable zu bekommen. Ich habe folgende Dinge versucht:

echo foo | myvar=$(</dev/stdin)
echo foo | myvar=$(cat)
echo foo | myvar=$(tee)

Aber $myvar ist leer.

Ich möchte nicht tun:

myvar=$(echo foo)

Weil ich keine Subshell erzeugen möchte.

Irgendwelche Ideen?

Bearbeiten : Ich möchte keine Unterschale erzeugen, da der Befehl vor der Pipe globale Variablen bearbeiten muss, was in einer Unterschale nicht möglich ist. Kann es? Das echo Ding dient nur zur Vereinfachung. Es ist eher so:

complex_function | myvar=$(</dev/stdin)

Und ich verstehe nicht, warum das nicht funktioniert. Dies funktioniert zum Beispiel:

complex_function | echo $(</dev/stdin)
9
Parckwart

Befehlssubstitution verwenden:

myvar=`echo foo`

oder

myvar=$(echo foo)
8
Zumo de Vidrio

Die richtige Lösung besteht darin, die Befehlssubstitution wie folgt zu verwenden:

variable=$(complex_command)

wie in

message=$(echo 'hello')

(oder in diesem Fall message=hello).

Ihre Pipeline:

echo 'hello' | message=$(</dev/stdin)

oder

echo 'hello' | read message

funktioniert tatsächlich. Das einzige Problem ist, dass die von Ihnen verwendete Shell den zweiten Teil der Pipeline in einer Subshell ausführt. Diese Subshell wird beim Beenden der Pipeline zerstört, sodass der Wert von $message In Shell nicht beibehalten wird.

Hier können Sie sehen, dass es funktioniert:

$ echo 'hello' | { read message; echo "$message" }
hello

... aber da die Umgebung der Subshell getrennt ist (und weg ist):

$ echo "$message"

(keine Leistung)

Eine Lösung für Sie wäre, zu ksh93 Zu wechseln, was diesbezüglich klüger ist:

$ echo 'hello' | read message
$ echo "$message"
hello

Eine andere Lösung für bash wäre das Festlegen der Shell-Option lastpipe. Dadurch würde der letzte Teil der Pipeline in der aktuellen Umgebung ausgeführt. Dies funktioniert jedoch nicht in interaktiven Shells, da lastpipe erfordert, dass die Jobsteuerung nicht aktiv ist.

#!/bin/bash

shopt -s lastpipe
echo 'hello' | read message
echo "$message"
8
Kusalananda

In ksh93 Können Sie Folgendes verwenden:

var=${
  my command that updates global variable
}

Dies ist eine Form der Befehlssubstitution, bei der keine Unterschale erzeugt wird. Bei Befehlen, die eingebaute Befehle sind, werden sie nicht in eine Pipe geschrieben (für die Sie unterschiedliche Prozesse zum Lesen und Schreiben in der Pipe benötigen, um Deadlocks zu vermeiden). ksh93 Lässt sie nur nicht Geben Sie alles andere als das aus, was sie ausgegeben hätten, um die Erweiterung zu bilden.

$ ksh -c 'a=${ b=123; echo foo;}; echo "$a $b"'
foo 123

Die Befehlssubstitution von fish verhält sich ebenfalls folgendermaßen:

$ fish -c 'set a (set b 123; echo foo); echo $a $b'
foo 123

In den meisten anderen Shells verwenden Sie eine temporäre Datei:

my command that updates global variable > file
var=$(cat file) # can be optimised to $(<file) with some shells

Unter Linux und mit bash oder zsh (die temporäre Dateien für <<< Verwenden) können Sie Folgendes tun:

{ my command that updates global variable > /dev/fd/3 &&
  var=$(cat<&3); } 3<<< ''
3