Ich versuche, bash dazu zu bringen, Daten von stdin zu verarbeiten, in die weitergeleitet wird, aber kein Glück. Was ich meine, ist keine der folgenden Arbeiten:
echo "hello world" | test=($(< /dev/stdin)); echo test=$test
test=
echo "hello world" | read test; echo test=$test
test=
echo "hello world" | test=`cat`; echo test=$test
test=
wo ich die Ausgabe haben möchte test=hello world
. Ich habe versucht, "" Anführungszeichen zu setzen "$test"
, was auch nicht funktioniert.
shopt -s lastpipe
- tldp.org/LDP/abs/html/bashver4.html#LASTPIPEOPTAntworten:
Verwenden
Sie können versuchen
read
, von einer Pipe wie folgt zu akzeptieren:oder schreiben Sie sogar eine Funktion wie diese:
Aber es hat keinen Sinn - Ihre Variablenzuweisungen halten möglicherweise nicht an! Eine Pipeline kann eine Subshell erzeugen, in der die Umgebung nach Wert und nicht nach Referenz vererbt wird. Aus diesem Grund
read
kümmert es sich nicht um die Eingabe von einer Pipe - sie ist undefiniert.FYI, http://www.etalabs.net/sh_tricks.html ist eine raffinierte Sammlung der Kruft, die notwendig ist, um die Kuriositäten und Inkompatibilitäten von Bourne-Muscheln zu bekämpfen, sh.
quelle
test=`echo "hello world" | { read test; echo $test; }`
{}
statt()
in Gruppieren dieser beiden Befehle?read
, Eingaben von der Pipe vorzunehmen, sondern die Variable in derselben Shell zu verwenden, in der die ausgeführt wirdread
.bash permission denied
beim Versuch, diese Lösung zu verwenden. Mein Fall ist ganz anders, aber ich konnte nirgendwo eine Antwort darauf finden. Was für mich funktioniert hat, war (ein anderes Beispiel, aber eine ähnliche Verwendung) :pip install -U echo $(ls -t *.py | head -1)
. Für den Fall, dass jemand jemals ein ähnliches Problem hat und auf diese Antwort stößt wie ich.Wenn Sie viele Daten einlesen und jede Zeile einzeln bearbeiten möchten, können Sie Folgendes verwenden:
Wenn Sie die Zeilen in mehrere Wörter aufteilen möchten, können Sie anstelle von x mehrere Variablen wie folgt verwenden:
Alternative:
Aber sobald Sie anfangen, etwas wirklich Kluges mit solchen Dingen zu machen, sollten Sie sich für eine Skriptsprache wie Perl entscheiden, in der Sie so etwas ausprobieren können:
Es gibt eine ziemlich steile Lernkurve mit Perl (oder ich denke, eine dieser Sprachen), aber Sie werden es auf lange Sicht viel einfacher finden, wenn Sie etwas anderes als die einfachsten Skripte tun möchten. Ich würde das Perl-Kochbuch und natürlich die Perl-Programmiersprache von Larry Wall et al. Empfehlen.
quelle
read
liest nicht aus einer Pipe (oder möglicherweise geht das Ergebnis verloren, weil die Pipe eine Unterschale erstellt). Sie können jedoch eine Here-Zeichenfolge in Bash verwenden:Weitere Informationen finden Sie in der Antwort von @ chepner
lastpipe
.quelle
Dies ist eine weitere Option
quelle
<(..)
gegenüber$(..)
besteht darin, dass<(..)
jede Zeile an den Anrufer zurückgegeben wird, sobald der von ihm ausgeführte Befehl sie verfügbar macht.$(..)
Wartet jedoch darauf, dass der Befehl seine gesamte Ausgabe abschließt und generiert, bevor er dem Aufrufer eine Ausgabe zur Verfügung stellt.Ich bin kein Experte für Bash, aber ich frage mich, warum dies nicht vorgeschlagen wurde:
Einzeiliger Beweis, dass es bei mir funktioniert:
quelle
bash
4.2 führt dielastpipe
Option ein, mit der Ihr Code wie geschrieben funktioniert, indem der letzte Befehl in einer Pipeline in der aktuellen Shell anstelle einer Subshell ausgeführt wird.quelle
Die Syntax für eine implizite Pipe von einem Shell-Befehl in eine Bash-Variable lautet
oder
In Ihren Beispielen leiten Sie Daten an eine Zuweisungsanweisung weiter, die keine Eingabe erwartet.
quelle
Der erste Versuch war ziemlich nah. Diese Variante sollte funktionieren:
und die Ausgabe ist:
Sie benötigen nach der Pipe geschweifte Klammern, um die zu testende Zuordnung und das Echo einzuschließen.
Ohne die geschweiften Klammern befindet sich die zu testende Zuordnung (nach der Pipe) in einer Shell, und das Echo "test = $ test" befindet sich in einer separaten Shell, die nichts über diese Zuordnung weiß. Aus diesem Grund wurde in der Ausgabe "test =" anstelle von "test = hello world" angezeigt.
quelle
In meinen Augen ist der beste Weg, um von stdin in bash zu lesen, der folgende, mit dem Sie auch an den Zeilen arbeiten können, bevor die Eingabe endet:
quelle
Weil ich darauf hereinfalle, möchte ich eine Notiz hinterlassen. Ich habe diesen Thread gefunden, weil ich ein altes sh-Skript neu schreiben muss, um POSIX-kompatibel zu sein. Dies bedeutet im Grunde, das von POSIX verursachte Rohr- / Unterschalenproblem zu umgehen, indem Code wie folgt umgeschrieben wird:
in:
Und Code wie folgt:
in:
Letzteres verhält sich jedoch bei leerer Eingabe nicht gleich. Mit der alten Notation wird die while-Schleife nicht bei leerer Eingabe eingegeben, sondern in der POSIX-Notation! Ich denke, es liegt an der Newline vor EOF, die nicht weggelassen werden kann. Der POSIX-Code, der sich eher wie die alte Notation verhält, sieht folgendermaßen aus:
In den meisten Fällen sollte dies gut genug sein. Leider verhält sich dies immer noch nicht genau wie die alte Notation, wenn some_command eine leere Zeile druckt. In der alten Notation wird der while-Körper ausgeführt und in der POSIX-Notation brechen wir vor dem Körper.
Ein Ansatz, um dies zu beheben, könnte folgendermaßen aussehen:
quelle
Ein intelligentes Skript, das sowohl Daten aus PIPE- als auch Befehlszeilenargumenten lesen kann:
Ausgabe:
Erläuterung: Wenn ein Skript Daten über eine Pipe empfängt, ist stdin / proc / self / fd / 0 ein Symlink zu einer Pipe.
Wenn nicht, zeigt es auf das aktuelle Terminal:
Die Bash-
[[ -p
Option kann überprüfen, ob es sich um eine Pipe handelt oder nicht.cat -
liest das vonstdin
.Wenn wir verwenden,
cat -
wenn es keine gibtstdin
, wird es ewig warten, deshalb setzen wir es in denif
Zustand.quelle
/dev/stdin
einen Link zu/proc/self/fd/0
Etwas in einen Ausdruck mit einer Aufgabe zu leiten, verhält sich nicht so.
Versuchen Sie stattdessen:
quelle
Der folgende Code:
wird auch funktionieren, aber es wird eine weitere neue Unterschale nach dem Rohr öffnen, wo
Gewohnheit.
Ich musste die Jobsteuerung deaktivieren, um die Methode von chepnars verwenden zu können (ich habe diesen Befehl vom Terminal aus ausgeführt):
Bash Manual sagt :
Hinweis: Die Jobsteuerung ist in einer nicht interaktiven Shell standardmäßig deaktiviert, sodass Sie das
set +m
Innere eines Skripts nicht benötigen .quelle
Ich denke, Sie haben versucht, ein Shell-Skript zu schreiben, das Eingaben von stdin entgegennehmen kann. Aber während Sie versuchen, es inline zu tun, haben Sie sich beim Versuch, diese test = -Variable zu erstellen, verlaufen. Ich denke, es macht nicht viel Sinn, es inline zu machen, und deshalb funktioniert es nicht so, wie Sie es erwarten.
Ich habe versucht zu reduzieren
um eine bestimmte Zeile von verschiedenen Eingaben zu erhalten. damit ich tippen konnte ...
Ich brauche also ein kleines Shell-Programm, das von stdin lesen kann. so wie du es tust.
los geht's
quelle
Wie wäre es damit:
quelle