String an stdin senden

157

Gibt es eine Möglichkeit, dies in Bash effektiv zu tun:

/my/bash/script < echo 'This string will be sent to stdin.'

Mir ist bewusst, dass ich die Ausgabe des Echos wie folgt weiterleiten könnte:

echo 'This string will be piped to stdin.' | /my/bash/script
Alle Arbeiter sind wesentlich
quelle
1
Was meinst du mit effektiv , warum ist Pipe kein Weg, dies zu tun?
Andy
Beide von Ihnen aufgelisteten Befehle sollten genau dasselbe tun. Welches Problem hast du?
Flimzy
5
@Flimzy: afaik, der erste wird nicht wie erwartet funktionieren, er wird versuchen, eine Datei namensecho
Andy
Oh, richtig. Was ist also los mit der zweiten Form?
Flimzy
2
@Flimzy: Außerdem öffnet das >Umleitungsformular einen Dateideskriptor als fd 0(stdin), während |opens einen untergeordneten Prozess startet und dessen stdout (fd 1) an das stdin des anderen Prozesses anfügt. Diese Tatsache kann nicht triviale Konsequenzen haben (denken Sie über das Teilen von Umgebungsvariablen nach?)
sehe

Antworten:

261

Sie können einzeilig verwenden heredoc

cat <<< "This is coming from the stdin"

das obige ist das gleiche wie

cat <<EOF
This is coming from the stdin
EOF

oder Sie können die Ausgabe von einem Befehl wie umleiten

diff <(ls /bin) <(ls /usr/bin)

oder du kannst lesen als

while read line
do
   echo =$line=
done < some_file

oder einfach

echo something | read param
jm666
quelle
Und wie kann man auf diese Weise Binärwerte eingeben? Ohne mit der Leitung (ich weiß , dass es mit dem Rohr durchgeführt werden kann , wie folgt: echo -e "\x01\x02..." | ./script)
cprcrack
Ich schreibe es gerne andersherum: <<< "Das kommt von stdin" perl ..., so sieht es aus wie die linke Seite des Rohrs.
Pyrolistical
@Pyrolistical ja! Besonders nützlich, wenn Sie beispielsweise einen Perl-Oneliner über eine Befehlszeile beherrschen - einfache Bearbeitung der Argumente von Perl, ohne dass Sie mit einem Cursor viel rückwärts bewegen müssen. :)
jm666
@ jm666 traurige Sache ist, ich habe gestern erfahren, wenn Sie einen Bash-Alias ​​verwenden, verwenden Sie einfach die Form command_alias <<< "stdin string", sonst heißt es Befehl nicht gefunden
Pyrolistical
@ jm666 Gibt es irgendwo etwas, über das ich mehr erfahren kann <<<? Ich schäme mich zuzugeben, dass ich es noch nie gesehen habe, und ich bin total verwirrt darüber. Ich habe versucht, dafür zu googeln, aber meine Ergebnisse haben nichts damit zu tun.
wpcarro
66

Du warst nah

/my/bash/script <<< 'This string will be sent to stdin.'

Für mehrzeilige Eingaben eignen sich Here-Docs:

/my/bash/script <<STDIN -o other --options
line 1
line 2
STDIN

Bearbeiten Zu den Kommentaren:

Um einen Binäreingang zu erreichen, sagen wir

xxd -r -p <<BINARY | iconv -f UCS-4BE -t UTF-8 | /my/bash/script
0000 79c1 0000 306f 0000 3061 0000 3093 0000 3077 0000 3093 0000 304b 0000 3093 0000 3077 0000 3093 0000 306a 0000 8a71 0000 306b 0000 30ca 0000 30f3 0000 30bb
0000 30f3 0000 30b9 0000 3092 0000 7ffb 0000 8a33 0000 3059 0000 308b 0000 3053 0000 3068 0000 304c 0000 3067 0000 304d 0000 000a
BINARY

Wenn Sie ersetzen catfür /my/bash/script(oder in der Tat das letzte Rohr fallen), dieser Druck:

私はちんぷんかんぷんな話にナンセンスを翻訳することができ

Oder wenn Sie etwas geekigeres wollten:

0000000: 0000 0000 bef9 0e3c 59f8 8e3c 0a71 d63c  .......<Y..<.q.<
0000010: c6f2 0e3d 3eaa 323d 3a5e 563d 090e 7a3d  ...=>.2=:^V=..z=
0000020: 7bdc 8e3d 2aaf a03d b67e b23d c74a c43d  {..=*..=.~.=.J.=
0000030: 0513 d63d 16d7 e73d a296 f93d a8a8 053e  ...=...=...=...>
0000040: 6583 0e3e 5a5b 173e 5b30 203e 3d02 293e  e..>Z[.>[0 >=.)>
0000050: d4d0 313e f39b 3a3e 6f63 433e 1c27 4c3e  ..1>..:>ocC>.'L>
0000060: cde6 543e 59a2 5d3e 9259 663e 4d0c 6f3e  ..T>Y.]>.Yf>M.o>
0000070: 60ba 773e cf31 803e ee83 843e 78d3 883e  `.w>.1.>...>x..>
0000080: 5720 8d3e 766a 913e beb1 953e 1cf6 993e  W .>vj.>...>...>
0000090: 7a37 9e3e c275 a23e dfb0 a63e bce8 aa3e  z7.>.u.>...>...>
00000a0: 441d af3e 624e b33e 017c b73e 0ca6 bb3e  D..>bN.>.|.>...>
00000b0: 6fcc bf3e 15ef c33e e90d c83e d728 cc3e  o..>...>...>.(.>
00000c0: c93f d03e ac52 d43e 6c61 d83e f36b dc3e  .?.>.R.>la.>.k.>
00000d0: 2f72 e03e 0a74 e43e 7171 e83e 506a ec3e  /r.>.t.>qq.>Pj.>
00000e0: 945e f03e 274e f43e f738 f83e f11e fc3e  .^.>'N.>.8.>...>
00000f0: 0000 003f 09ee 013f 89d9 033f 77c2 053f  ...?...?...?w..?
0000100: caa8 073f 788c 093f 776d 0b3f be4b 0d3f  ...?x..?wm.?.K.?
0000110: 4427 0f3f 0000 113f e8d5 123f f3a8 143f  D'.?...?...?...?
0000120: 1879 163f 4e46 183f 8d10 1a3f cad7 1b3f  .y.?NF.?...?...?
0000130: fe9b 1d3f 1f5d 1f3f 241b 213f 06d6 223f  ...?.].?$.!?.."?
0000140: bb8d 243f 3a42 263f 7cf3 273f 78a1 293f  ..$?:B&?|.'?x.)?
0000150: 254c 2b3f 7bf3 2c3f 7297 2e3f 0138 303f  %L+?{.,?r..?.80?
0000160: 22d5 313f ca6e 333f                      ".1?.n3?

Welches ist der Sinus der ersten 90 Grad in 4-Byte-Binär-Floats

sehe sehen
quelle
Und wie kann man auf diese Weise Binärwerte eingeben?
cprcrack
Ich würde xxd -r(oder od) verwenden, um das HIER-Dokument zu filtern
siehe
Könnten Sie es mit einem Beispiel erklären? Ich habe es nicht geschafft.
cprcrack
1
siehe bearbeitete Antwort. Es geht darum, keine binären Rohdaten in Ihr Skript aufzunehmen, sondern sie durch ein Programm wie xxd
sehe
Was ist der Sinn des Tuns: "/ my / bash / script <<< 'Diese Zeichenfolge wird an stdin gesendet.'" Wenn Sie direkt sagen können: "/ my / bash / script 'Diese Zeichenfolge wird an stdin gesendet. '"?
Baiyan Huang
2

Sie können auch verwenden , readwie dies

echo "enter your name"
read name
echo $name
Rahul
quelle
2

Lösung

Sie möchten (1) eine stdout-Ausgabe in einem Prozess erstellen (wie echo '…') und (2) diese Ausgabe auf die stdin-Eingabe eines anderen Prozesses umleiten, jedoch (3) ohne Verwendung des Bash-Pipe-Mechanismus. Hier ist eine Lösung, die alle drei Bedingungen erfüllt:

/my/bash/script < <(echo 'This string will be sent to stdin.')

Das <ist normal Eingabeumleitung für stdin. Das<(…) ist Bash-Prozess-Substitution. Etwa erstellt es eine /dev/fd/…Datei mit der Ausgabe des Ersetzungsbefehls und übergibt diesen Dateinamen anstelle von <(…), was hier zum Beispiel zu führt script < /dev/fd/123. Einzelheiten finden Sie in dieser Antwort

Vergleich mit anderen Lösungen

  • Ein einzeiliger Heredoc, der an stdin geschickt wurde script <<< 'string' ermöglicht nur das Senden statischer Zeichenfolgen, nicht die Ausgabe anderer Befehle.

  • Prozesssubstitution allein, wie in diff <(ls /bin) <(ls /usr/bin), sendet nichts an stdin. Stattdessen wird die Prozessausgabe als Inhalt von Dateien übergeben, die im Hintergrund erstellt wurden, was beispielsweise entsprichtdiff /dev/fd/10 /dev/fd/11 . In diesem Befehl diffwird keine Eingabe von stdin erhalten.

Anwendungsfälle

Ich mag das, im Gegensatz zum Rohrmechanismus, dem < <(…) den Befehl an erster Stelle und alle Eingaben danach setzt, wie es der Standard für die Eingabe über Befehlszeilenoptionen ist.

Über die Kommandozeilenästhetik hinaus gibt es jedoch einige Fälle, in denen ein Rohrmechanismus nicht verwendet werden kann. Zum Beispiel, wenn ein bestimmter Befehl als Argument für einen anderen Befehl angegeben werden muss, wie in diesem Beispiel mitsshpass .

Tanius
quelle
Interessante Alternative. Ist dies im Gegensatz zu POSIX-konform <<<?
Alle Arbeiter sind unerlässlich
0
cat | /my/bash/script

Ermöglicht es einem, mehrere Zeilen in ein Programm einzugeben, ohne dass diese Eingabe im Verlauf gespeichert oder in angezeigt wird ps. Drücken Sie einfach Strg + C, wenn Sie mit der Eingabe fertig sind cat.

Walf
quelle
-1

Aliase können und können nicht verrohrt stdin verarbeiten ...

Hier erstellen wir 3 Ausgabezeilen

$ echo -e "line 1\nline 2\nline 3"
line 1
line 2
line 3

Wir leiten die Ausgabe dann an stdin des Befehls sed weiter, um sie alle in eine Zeile zu setzen

$ echo -e "line 1\nline 2\nline 3" |  sed -e ":a;N;\$!ba ;s?\n? ?g"
line 1 line 2 line 3

Wenn wir einen Alias ​​desselben sed-Befehls definieren

$ alias oline='sed -e ":a;N;\$!ba ;s?\n? ?g"'

Wir können die Ausgabe an den Standard des Alias ​​weiterleiten und sie verhält sich genauso

$ echo -e "line 1\nline 2\nline 3" |  oline
line 1 line 2 line 3

Das Problem tritt auf, wenn wir versuchen, den Alias ​​als Funktion zu definieren

$ alias oline='function _oline(){ sed -e ":a;N;\$!ba ;s?\n? ?g";}_oline'

Das Definieren des Alias ​​als Funktion bricht die Pipe

$ echo -e "line 1\nline 2\nline 3" |  oline
>
KenB
quelle
Erstens beantwortet dies nicht die Frage - vielleicht haben Sie die falsche Frage beantwortet? Zweitens, warum würden Sie jemals eine Funktion innerhalb eines Alias ​​definieren? Du solltest es einfach tun function oline() { sed -e ":a;N;\$!ba ;s?\n? ?g"; }. Drittens wäre dieses Sed mit awk viel verständlicher:awk -F '\n' 'ORS=" " { print } END { printf "\n"}'
Leonardo Dagnino