Kirim string ke stdin

158

Apakah ada cara untuk melakukan ini secara efektif di bash:

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

Saya sadar bahwa saya dapat menyalurkan output dari gema seperti ini:

echo 'This string will be piped to stdin.' | /my/bash/script
Semua Pekerja Sangat Penting
sumber
1
Apa yang Anda maksud dengan efektif , mengapa tidak ada cara untuk melakukan ini?
Andy
Kedua perintah yang Anda daftarkan harus melakukan hal yang persis sama. Apa masalah yang Anda hadapi?
Flimzy
5
@Flimzy: afaik, yang pertama tidak akan berfungsi seperti yang diharapkan, ia akan mencoba untuk membuka file bernamaecho
Andy
Oh benar Jadi apa yang salah dengan bentuk kedua?
Flimzy
2
@Flimzy: selain itu, >bentuk pengalihan akan membuka file descriptor sebagai fd 0(stdin), sedangkan |membuka memulai proses anak dan atase stdout itu (fd 1) ke stdin proses lain. Fakta ini dapat memiliki konsekuensi non-sepele (pikirkan tentang berbagi variabel lingkungan?)
lihat

Jawaban:

262

Anda dapat menggunakan satu baris heredoc

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

di atas sama dengan

cat <<EOF
This is coming from the stdin
EOF

atau Anda dapat mengarahkan output dari perintah, seperti

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

atau Anda dapat membaca sebagai

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

atau sederhana

echo something | read param
jm666
sumber
Dan bagaimana cara memasukkan nilai biner dengan cara ini? Tanpa menggunakan pipa (saya tahu itu bisa dilakukan dengan pipa sebagai berikut: echo -e "\x01\x02..." | ./script)
cprcrack
Saya suka menulis dengan cara lain: <<< "Ini berasal dari stdin" perl ..., dengan cara ini sepertinya sisi kiri pipa.
Pirolistik
@Prolitik ya! Terutama berguna ketika menguasai misalnya perl oneliner dari baris perintah - mengedit argumen perl dengan mudah tanpa perlu banyak gerakan mundur dengan kursor. :)
jm666
@ jm666 hal yang menyedihkan adalah saya pelajari kemarin jika Anda menggunakan alias bash, Anda hanya menggunakan formulir command_alias <<< "stdin string", jika tidak maka akan mengatakan perintah tidak ditemukan
Pyrolistic
@ jm666 Apakah ada tempat yang bisa saya pelajari lebih lanjut <<<? Saya malu mengakui bahwa saya belum pernah melihatnya sebelumnya, dan saya benar-benar bingung karenanya. Saya mencoba Googling untuk itu, tetapi hasil saya tidak berhubungan.
wpcarro
66

Anda sudah dekat

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

Untuk input multiline, di sini-dok cocok:

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

Edit Untuk komentar:

Untuk mencapai input biner, katakan

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

Jika Anda mengganti catuntuk /my/bash/script(atau memang menjatuhkan pipa terakhir), cetakan ini:

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

Atau, jika Anda menginginkan sesuatu yang sedikit lebih culun:

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?

Yang merupakan sinus 90 derajat pertama dalam mengapung biner 4byte

lihat
sumber
Dan bagaimana cara memasukkan nilai biner dengan cara ini?
cprcrack
Saya akan menggunakan xxd -r(atau od) untuk memfilter dokumen DI SINI
lihat
Bisakah Anda menjelaskannya dengan sebuah contoh? Saya tidak berhasil melakukannya.
cprcrack
1
lihat jawaban yang diedit. Intinya adalah untuk tidak memasukkan data biner mentah dalam skrip Anda, tetapi sebaliknya memfilternya melalui program seperti xxd
sehe
Apa gunanya melakukan: "/ my / bash / script <<< 'String ini akan dikirim ke stdin.'" Ketika Anda dapat langsung mengatakan: "/ my / bash / script 'String ini akan dikirim ke stdin. '"
Baiyan Huang
2

Anda juga bisa menggunakan readseperti ini

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

Larutan

Anda ingin (1) membuat output stdout dalam satu proses (seperti echo '…' ) dan (2) mengarahkan output itu ke input stdin dari proses lain tetapi (3) tanpa menggunakan mekanisme pipa bash. Inilah solusi yang cocok dengan ketiga kondisi:

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

Ini <adalah pengalihan input normal untuk stdin. The <(…)adalah proses pesta substitusi. Secara kasar itu membuat /dev/fd/…file dengan output dari perintah substitusi dan meneruskan nama file itu di tempat<(…) , menghasilkan di sini misalnya di script < /dev/fd/123. Untuk detailnya, lihat jawaban ini

Perbandingan dengan solusi lain

  • Heredoc satu baris dikirim ke stdin script <<< 'string' hanya memungkinkan untuk mengirim string statis, bukan output dari perintah lain.

  • Substitusi proses saja, seperti di diff <(ls /bin) <(ls /usr/bin), tidak mengirim apa pun ke stdin. Sebagai gantinya, proses output diteruskan sebagai konten file yang dibuat di latar belakang, setara dengan misalnya diff /dev/fd/10 /dev/fd/11. Dalam perintah itu,diff tidak mendapat input dari stdin.

Gunakan kasing

Saya suka itu, tidak seperti mekanisme pipa, itu < <(…) mekanisme ini memungkinkan untuk menempatkan perintah terlebih dahulu dan semua input setelahnya, seperti standar untuk input dari opsi baris perintah.

Namun, di luar estetika commandline, ada beberapa kasus di mana mekanisme pipa tidak dapat digunakan. Misalnya, ketika perintah tertentu harus disediakan sebagai argumen untuk perintah lain, seperti dalam contoh ini dengansshpass .

tanius
sumber
Alternatif yang menarik. Apakah ini tidak sesuai dengan POSIX <<<?
Semua Pekerja Sangat Penting
0
cat | /my/bash/script

Memungkinkan seseorang untuk mengetik beberapa baris ke dalam suatu program, tanpa input yang disimpan dalam riwayat, atau terlihat di ps. Cukup tekan Ctrl + C saat selesai mengetik hingga selesai cat.

Walf
sumber
-1

alias dapat dan tidak dapat memproses ...

Di sini kita membuat 3 baris output

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

Kami kemudian menyalurkan output ke stdin dari perintah sed untuk menempatkan mereka semua pada satu baris

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

Jika kita mendefinisikan alias dari perintah sed yang sama

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

Kita dapat menyalurkan output ke stdin alias dan berperilaku sama persis

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

Masalah muncul ketika kami mencoba mendefinisikan alias sebagai fungsi

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

Menentukan alias sebagai funstion merusak pipa

$ echo -e "line 1\nline 2\nline 3" |  oline
>
KenB
sumber
Pertama, ini tidak menjawab pertanyaan - mungkin Anda menjawab pertanyaan yang salah? Kedua, mengapa Anda pernah mendefinisikan fungsi di dalam alias? Anda harus melakukannya function oline() { sed -e ":a;N;\$!ba ;s?\n? ?g"; }. Ketiga, sed ini akan jauh lebih dimengerti dengan awk:awk -F '\n' 'ORS=" " { print } END { printf "\n"}'
Leonardo Dagnino