Wie verkette ich stdin und einen String?


107

Wie verkette ich stdin mit einem String wie diesem?

echo "input" | COMMAND "string"

und bekomme

inputstring

Antworten:


119

Ein bisschen hacky, aber dies könnte der kürzeste Weg zu tun , was man in der Frage gestellt (ein Rohr verwenden zu akzeptieren stdoutaus echo "input"als stdinzu einem anderen Prozess / Befehl ein :

echo "input" | awk '{print $1"string"}'

Ausgabe:

inputstring

Welche Aufgabe versuchst du genau zu erfüllen? Mehr Kontext kann Ihnen mehr Orientierung für eine bessere Lösung geben.

Update - Antwort auf Kommentar:

@ NoamRoss

Die idiomatischere Art, das zu tun, was Sie wollen, ist dann:

echo 'http://dx.doi.org/'"$(pbpaste)"

Die $(...)Syntax wird als Befehlssubstitution bezeichnet . Kurz gesagt, es führt die Befehle aus, die in einer neuen Subshell enthalten sind, und ersetzt die stdoutAusgabe dort, wo sie $(...)in der übergeordneten Shell aufgerufen wurde. Sie würden also tatsächlich Folgendes erhalten:

echo 'http://dx.doi.org/'"rsif.2012.0125"

1
Vielen Dank! Das funktioniert super. Die genaue Aufgabe, die ich zu erfüllen versuche, besteht darin, eine Zeichenfolge aus der Zwischenablage (einem DOI) zu entnehmen und ihr eine URL voranzustellen. Damit mache ich pbpaste | awk '{print "http://dx.doi.org/"$1}'und bekommehttp://dx.doi.org/10.1098/rsif.2012.0125
Noam Ross

5
@ Sampson-Chen, ich würde verwenden '{print $0"string"}', um die ganze Sache zu schnappen.
Roman Newaza

3
Es wird tatsächlich stringan jede Zeile angehängt . Versuchen Sie es echo 'input'\n'another line' | awk '{print $0"string"}'.
Tomékwi

55

Verwenden cat -Sie diese $()Option , um aus stdin zu lesen, und setzen Sie sie ein, um die nachfolgende Newline wegzuwerfen

echo input | COMMAND "$(cat -)string"

Warum lassen Sie die Pipe jedoch nicht fallen und greifen bei einer Befehlsersetzung auf die Ausgabe der linken Seite zu:

COMMAND "$(echo input)string"

1
Hier ist ein praktisches Beispiel: find ~ / other_program / lib -name "* .jar" | tr '\ n' ':' | Echo "$ (cat -) ~ / java_app / classes"
Ashwin Jayaprakash

2
Dies funktioniert bei mir in bash, aber in zsh erhalte ich "cat: -: Eingabe- / Ausgabefehler". Irgendeine Idee, was das verursachen könnte?
Jaymmer - Wiedereinsetzung Monica

"COMMAND" steht für die Lösung und "Echo Input" für einen komplizierteren Prozess. Das Argument "-" für cat ist nur erforderlich, wenn andere Dateiargumente vorhanden sind. Andernfalls ist es die Standardeinstellung. Sie meinten also: Echoeingang | echo $ (cat) string
Denis Howe

45

Ich benutze oft Pipes, daher ist dies eine einfache Möglichkeit, stdin voranzustellen und zu ergänzen:

echo -n "my standard in" | cat <(echo -n "prefix... ") - <(echo " ...suffix")
prefix... my standard in ...suffix

2
Vielen Dank! Das ist eigentlich ein sehr cooles Beispiel für die Verwendung von pipeundcat
Alex Ivasyuv

1
Dies sollte die beste Antwort sein
Chris Koston

1
Warum nicht einfach : echo "my standard in" | echo -e "prefix\n$(cat -)\nsuffix"? Oder die besser lesbare Version:echo "my standard in" | printf "%s\n%s\n%s\n" "prefix" "$(cat -)" "suffix"
MiniMax

1
@MiniMax Da die Antwort bei Streams gut funktioniert, funktioniert sie bei großen Standardwerten.
Anishpatel

1
@anishpatel Meine Version funktioniert auch für große stdin. Kein Unterschied.
MiniMax

11

Sie können es mit sed tun:

seq 5 | sed '$a\6'
seq 5 | sed '$ s/.*/\0 6/'

In Ihrem Beispiel:

echo input | sed 's/.*/\0string/'

9

Es gibt einige Möglichkeiten, dies zu erreichen. Ich persönlich denke, das Beste ist:

echo input | while read line; do echo $line string; done

Eine andere Möglichkeit besteht darin, "$" (Zeilenendezeichen) in einem sed-Befehl durch "string" zu ersetzen:

echo input | sed "s/$/ string/g"

Warum bevorzuge ich das erstere? Weil es eine Zeichenfolge sofort mit stdin verkettet, zum Beispiel mit dem folgenden Befehl:

(echo input_one ;sleep 5; echo input_two ) | while read line; do echo $line string; done

Sie erhalten sofort die erste Ausgabe:

input_one string

und dann nach 5 Sekunden erhalten Sie das andere Echo:

input_two string

Wenn Sie dagegen "sed" verwenden, wird zuerst der gesamte Inhalt der Klammer ausgeführt und dann "sed", also der Befehl

(echo input_one ;sleep 5; echo input_two ) | sed "s/$/ string/g"

gibt beide Zeilen aus

input_one string
input_two string

nach 5 Sekunden.

Dies kann sehr nützlich sein, wenn Sie Funktionen aufrufen, deren Ausführung lange dauert und die über die Ausgabe der Funktion kontinuierlich aktualisiert werden sollen.


Tatsächlich verarbeitet die Option sed auch jede Eingabezeile sofort.
Tomékwi

Für eine einzelne Eingabezeile ist die einfachste Lösung die Echoeingabe | (read v; echo $ {v} string) Das ist reine Shell und erfordert keinen zusätzlichen Prozess wie sed.
Denis Howe

7

Ich weiß, dass dies einige Jahre zu spät ist, aber Sie können dies mit der Option xargs -J erreichen:

echo "input" | xargs -J "%" echo "%" "string"

Und da es sich um xargs handelt, können Sie dies in mehreren Zeilen einer Datei gleichzeitig tun. Wenn die Dateinamen drei Zeilen haben, wie zum Beispiel:

Adam
Bob
Charlie

Du könntest es tun:

cat names | xargs -n 1 -J "%" echo "I like" "%" "because he is nice"

1
Sieht cool aus, -Jscheint aber nicht Standard / üblich zu sein. Unter Linux (wo xargsist ein Teil davon GNU findutils) erhalte ich die Fehlermeldung: Auf xargs: invalid option -- 'J'welchem ​​System ist das?
Arielf

3
-Jist für die Mac-Version. Für Linux -Iführt die gleiche Funktion aus.
user2635263

1
Vielen Dank! sehr hilfreich. Bitte beachten Sie, dass diese vereinfachte Version unter Linux genauso gut funktioniert: cat names | xargs -I% echo "I like % because he is nice"IOW: Keine Notwendigkeit für -n 1( xargsAufrufe echoeinmal pro Eingabezeile, da -Iimpliziert -L1). Außerdem scheinen alle separaten Arg-Anführungszeichen redundant zu sein.
Arielf

3

Der Befehl, den Sie veröffentlicht haben, verwendet die Zeichenfolge "input" und verwendet sie als stdin-Stream von COMMAND. Dies würde nur dann zu den gewünschten Ergebnissen führen, wenn COMMAND zuerst den Inhalt seines stdin und dann seine Befehlszeilenargumente ausgedruckt hat.

Es scheint, als ob das, was Sie tun möchten, der Befehlsersetzung näher kommt.

http://www.gnu.org/software/bash/manual/html_node/Command-Substitution.html#Command-Substitution

Mit der Befehlsersetzung können Sie eine Befehlszeile wie folgt haben:

echo input `COMMAND "string"`

Dies wertet zuerst COMMAND mit "string" als Eingabe aus und erweitert dann die Ergebnisse dieser Befehlsausführung auf eine Zeile, wobei ersetzt wird, was zwischen den '`' Zeichen steht.


und natürlich @NaomRoss, es sei denn, Sie müssen die Bourne-Shell verwenden oder andere verrückte "Portabilitäts" -Mandate haben, verwenden Sie die moderne Befehlsersetzung wie echo input $(COMMAND "string")anstelle von Backticks. Viel Glück für jeden.
Shellter


0

Funktioniert auch:

seq -w 0 100 | xargs -I {} echo "string "{}

Erzeugt Zeichenfolgen wie:

string 000
string 001
string 002
string 003
string 004

...

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.