Invia stringa a stdin


158

C'è un modo per farlo efficacemente in bash:

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

Sono consapevole che potrei convogliare l'output dell'eco in questo modo:

echo 'This string will be piped to stdin.' | /my/bash/script

1
Cosa intendi con efficacia , perché la pipa non è un modo per farlo?
Andy,

Entrambi i comandi che hai elencato dovrebbero fare esattamente la stessa cosa. Che problema hai?
Flimzy,

5
@Flimzy: afaik, il primo non funzionerà come previsto, proverà ad aprire un file chiamatoecho
Andy,

Oh giusto. Quindi cosa c'è che non va nel secondo modulo?
Flimzy,

2
@Flimzy: inoltre, il >modulo di reindirizzamento aprirà un descrittore di file come fd 0(stdin), mentre |opens avvia un processo figlio e allega il suo stdout (fd 1) allo stdin dell'altro processo. Questo fatto può avere conseguenze non banali (pensate alla condivisione delle variabili d'ambiente?)
vedi il

Risposte:


262

Puoi usare una riga heredoc

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

quanto sopra è uguale a

cat <<EOF
This is coming from the stdin
EOF

oppure puoi reindirizzare l'output da un comando, ad esempio

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

oppure puoi leggere come

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

o semplicemente

echo something | read param

E come inserire valori binari in questo modo? Senza usare il tubo (so che può essere fatto con il tubo come segue: echo -e "\x01\x02..." | ./script)
cprcrack

Mi piace scriverlo nell'altro modo: <<< "Questo viene dallo stdin" perl ..., in questo modo sembra il lato sinistro della pipa.
Pirolistico

@Pololistica sì! Particolarmente utile quando si padroneggia ad esempio un perl oneliner da una riga di comando - facile modifica degli argomenti di perl senza la necessità di molti movimenti all'indietro con un cursore. :)
jm666,

@ jm666 cosa triste ho imparato ieri se usi un alias bash, basta usare il modulo command_alias <<< "stringa stdin", altrimenti dirà comando non trovato
Pirolistico

@ jm666 C'è un posto dove posso saperne di più <<<? Mi vergogno di ammettere di non averlo mai visto prima e ne sono totalmente sconcertato. Ho provato a cercarlo su Google, ma i miei risultati non sono stati correlati.
wpcarro,

66

Eri vicino

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

Per input multilinea, qui-documenti sono adatti:

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

Modifica ai commenti:

Per ottenere un input binario, diciamo

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

Se sostituite catper /my/bash/script(o addirittura cadere l'ultimo pipe), questo stampa:

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

Oppure, se volevi qualcosa di un po 'più geniale:

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?

Qual è il seno dei primi 90 gradi nei galleggianti binari a 4 byte


E come inserire valori binari in questo modo?
cprcrack,

Userei xxd -r(o od) per filtrare il documento QUI
sehe

Potresti spiegarlo con un esempio? Non sono riuscito a farlo.
cprcrack,

1
vedi risposta modificata. Il punto è non includere dati binari grezzi nel tuo script, ma invece filtrarli attraverso un programma come
xxd

Qual è il punto di fare: "/ my / bash / script <<< 'Questa stringa verrà inviata a stdin.'" Quando puoi dire direttamente: "/ my / bash / script 'Questa stringa verrà inviata a stdin. '"?
Baiyan Huang,

2

Puoi anche usare readcosì

echo "enter your name"
read name
echo $name

2

Soluzione

Si desidera (1) creare l'output stdout in un processo (come echo '…') e (2) reindirizzare quell'output all'input stdin di un altro processo ma (3) senza l'uso del meccanismo bash pipe. Ecco una soluzione che soddisfa tutte e tre le condizioni:

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

È il <normale reindirizzamento di input per stdin. La <(…)sostituzione del processo è bash. All'incirca crea un /dev/fd/…file con l'output del comando sostitutivo e passa quel nome file al posto di <(…), risultando qui per esempio in script < /dev/fd/123. Per i dettagli, vedi questa risposta

Confronto con altre soluzioni

  • Un'eredità di una riga inviata a stdin script <<< 'string'consente solo di inviare stringhe statiche, non l'output di altri comandi.

  • La sola sostituzione del processo, come in diff <(ls /bin) <(ls /usr/bin), non invia nulla a stdin. Al contrario, l'output del processo viene passato come contenuto dei file creati in background, equivalente ad esempio diff /dev/fd/10 /dev/fd/11. In quel comando, diffnon riceve input dallo stdin.

Casi d'uso

Mi piace il fatto che, a differenza del meccanismo pipe, il < <(…)meccanismo consente di inserire prima il comando e tutti gli input, come lo standard per l'input dalle opzioni della riga di comando.

Tuttavia, al di là dell'estetica da riga di comando, ci sono alcuni casi in cui un meccanismo a tubo non può essere utilizzato. Ad esempio, quando un determinato comando deve essere fornito come argomento a un altro comando, come in questo esempio consshpass .


Alternativa interessante Questo a differenza di POSIX è conforme <<<?
Tutti i lavoratori sono essenziali

0
cat | /my/bash/script

Consente di digitare più righe in un programma, senza che l'input venga salvato nella cronologia, né visibile in ps. Premi Ctrl + C quando hai finito di digitare fino alla fine cat.


-1

gli alias possono e non possono elaborare stdin convogliati ...

Qui creiamo 3 linee di output

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

Quindi reindirizziamo l'output allo stdin del comando sed per metterli tutti su una riga

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

Se definiamo un alias dello stesso comando sed

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

Possiamo inoltrare l'output allo stdin dell'alias e si comporta esattamente allo stesso modo

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

Il problema sorge quando proviamo a definire l'alias come una funzione

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

La definizione dell'alias come funstion rompe la pipa

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

Innanzitutto, questo non risponde alla domanda - forse hai risposto alla domanda sbagliata? In secondo luogo, perché mai definire una funzione all'interno di un alias? Dovresti semplicemente farlo function oline() { sed -e ":a;N;\$!ba ;s?\n? ?g"; }. In terzo luogo, questa sed sarebbe molto più comprensibile con awk:awk -F '\n' 'ORS=" " { print } END { printf "\n"}'
Leonardo Dagnino il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.