ส่งสตริงไปยัง stdin


158

มีวิธีในการทำเช่นนี้อย่างมีประสิทธิภาพในทุบตี:

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

ฉันรู้ว่าฉันสามารถส่งออกท่อจากเสียงสะท้อนเช่นนี้:

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

1
คุณหมายถึงอะไรอย่างมีประสิทธิภาพทำไมท่อไม่ทำวิธีนี้
Andy

คำสั่งทั้งสองที่คุณระบุไว้ควรทำสิ่งเดียวกัน คุณมีปัญหาอะไร
Flimzy

5
@Flimzy: afaik คนแรกไม่ทำงานอย่างที่คาดไว้มันจะพยายามเปิดไฟล์ที่เรียกว่าecho
Andy

โอ้ใช่. แล้วเกิดอะไรขึ้นกับรูปแบบที่สอง?
Flimzy

2
@Flimzy: นอกจากนี้>รูปแบบการเปลี่ยนเส้นทางจะเปิดไฟล์ descriptor เป็น fd 0(stdin) ในขณะที่การ|เปิดเริ่มกระบวนการเด็กและแนบมัน stdout (fd 1) เพื่อ stdin กระบวนการอื่น ๆ ความจริงเรื่องนี้สามารถมีผลกระทบที่ไม่น่ารำคาญ (คิดว่าเกี่ยวกับการแบ่งปันตัวแปรสภาพแวดล้อม?)
sehe

คำตอบ:


262

คุณสามารถใช้หนึ่งบรรทัด heredoc

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

ด้านบนเหมือนกับ

cat <<EOF
This is coming from the stdin
EOF

หรือคุณสามารถเปลี่ยนเส้นทางผลลัพธ์จากคำสั่งเช่น

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

หรือคุณสามารถอ่านเป็น

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

หรือเพียงแค่

echo something | read param

และวิธีการป้อนค่าไบนารีด้วยวิธีนี้ โดยไม่ต้องใช้ท่อ (ฉันรู้ว่ามันสามารถทำได้ด้วยท่อดังต่อไปนี้echo -e "\x01\x02..." | ./script)
cprcrack

ฉันชอบที่จะเขียนมันด้วยวิธีอื่น: <<< "นี่มาจาก stdin" perl ... ด้วยวิธีนี้ดูเหมือนว่ามือซ้ายของท่อ
Pyrolistical

@Pyrolistical ใช่! มีประโยชน์โดยเฉพาะอย่างยิ่งเมื่อการเรียนรู้ตัวอย่างเช่น perl oneliner จากบรรทัดคำสั่ง - แก้ไขข้อโต้แย้งของ perl ได้ง่ายโดยไม่จำเป็นต้องเคลื่อนไหวย้อนหลังมากนักด้วยเคอร์เซอร์ :)
jm666

@ jm666 สิ่งที่น่าเศร้าคือฉันได้เรียนรู้เมื่อวานนี้ถ้าคุณใช้นามแฝงทุบตีคุณเพียงแค่ใช้รูปแบบ command_alias <<< "สตริง stdin" มิฉะนั้นจะพูดว่าไม่พบคำสั่ง
Pyrolistical

@ jm666 มีที่ไหนอีก<<<บ้างที่ฉันสามารถเรียนรู้เพิ่มเติมเกี่ยวกับ? ฉันละอายใจที่จะยอมรับว่าฉันไม่เคยเห็นมาก่อนและฉันก็ประหลาดใจกับมัน ฉันลองใช้ Google กับมัน แต่ผลลัพธ์ของฉันไม่เกี่ยวข้องกัน
wpcarro

66

คุณสนิท

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

สำหรับการป้อนหลายบรรทัดที่นี่ -dcs เหมาะ:

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

แก้ไขความคิดเห็น:

เพื่อให้บรรลุการป้อนข้อมูลแบบไบนารีพูด

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

หากคุณใช้แทนcatสำหรับ/my/bash/script(หรืออันที่จริงวางท่อสุดท้าย), พิมพ์นี้:

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

หรือถ้าคุณต้องการบางสิ่งที่เกินบรรยาย:

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?

ซึ่งเป็นไซน์ของ 90 องศาแรกใน 4byte ไบนารีลอย


และวิธีการป้อนค่าไบนารีด้วยวิธีนี้
cprcrack

ฉันจะใช้xxd -r(หรือod) เพื่อกรองเอกสาร HERE
sehe

คุณช่วยอธิบายด้วยตัวอย่างได้ไหม ฉันไม่สามารถทำได้
cprcrack

1
ดูคำตอบที่แก้ไข จุดคือการไม่รวมถึงข้อมูลไบนารีดิบในสคริปต์ของคุณ แต่แทนที่จะกรองมันผ่านโปรแกรมเช่น xxd
sehe

จุดประสงค์คืออะไร: "/ my / bash / script <<< 'สตริงนี้จะถูกส่งไปยัง stdin'" เมื่อคุณสามารถพูดได้โดยตรงว่า: "/ my / bash / script" สตริงนี้จะถูกส่งไปยัง stdin '"
Baiyan Huang


2

สารละลาย

คุณต้องการ (1) สร้างเอาต์พุต stdout ในกระบวนการเดียว (เช่นecho '…') และ (2) เปลี่ยนเส้นทางเอาต์พุตนั้นไปยังอินพุต stdin ของกระบวนการอื่น แต่ (3) โดยไม่ต้องใช้กลไกทุบตีท่อ นี่คือวิธีการแก้ปัญหาที่ตรงกับเงื่อนไขทั้งสาม:

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

การ<เปลี่ยนเส้นทางอินพุตปกติสำหรับ stdin การ<(…)ทดแทนกระบวนการ bash คือ ประมาณมันจะสร้าง/dev/fd/…ไฟล์ที่มีผลลัพธ์ของคำสั่งแทนและส่งผ่านชื่อไฟล์ว่าในสถานที่ของผลที่นี่เช่นใน<(…) script < /dev/fd/123สำหรับรายละเอียดดูคำตอบนี้

เปรียบเทียบกับโซลูชันอื่น ๆ

  • heredoc บรรทัดเดียวที่ส่งไปยัง stdin script <<< 'string'อนุญาตให้ส่งสตริงแบบสแตติกเท่านั้นไม่ใช่เอาต์พุตของคำสั่งอื่น

  • การทดแทนกระบวนการเพียงอย่างเดียวเช่นในdiff <(ls /bin) <(ls /usr/bin)จะไม่ส่งสิ่งใด ๆ ไปยัง stdin diff /dev/fd/10 /dev/fd/11แต่การส่งออกขั้นตอนจะถูกส่งเป็นเนื้อหาของไฟล์ที่สร้างขึ้นในพื้นหลังที่เทียบเท่ากับการยกตัวอย่างเช่น ในคำสั่งนั้นdiffไม่ได้รับอินพุตจาก stdin

ใช้กรณี

ฉันชอบสิ่งนี้ซึ่งแตกต่างจากกลไกของท่อกลไก< <(…)อนุญาตให้ใส่คำสั่งแรกและอินพุตทั้งหมดหลังจากนั้นเช่นเดียวกับมาตรฐานสำหรับอินพุตจากตัวเลือกบรรทัดคำสั่ง

อย่างไรก็ตามนอกเหนือจาก commandline สุนทรียภาพมีบางกรณีที่ไม่สามารถใช้กลไกไปป์ ตัวอย่างเช่นเมื่อคำสั่งบางอย่างจะต้องมีการให้เป็นอาร์กิวเมนต์คำสั่งอื่นเช่นในตัวอย่างนี้ด้วยsshpass


ทางเลือกที่น่าสนใจ สิ่งนี้เกิดขึ้นได้กับ POSIX ที่ไม่เหมือน<<<หรือไม่?
คนงานทุกคนมีความจำเป็น

0
cat | /my/bash/script

psช่วยหนึ่งที่จะพิมพ์หลายบรรทัดลงในโปรแกรมโดยไม่ต้องป้อนข้อมูลที่บันทึกไว้ในประวัติศาสตร์หรือในที่มองเห็นได้ เพียงแค่กดปุ่ม Ctrl + C catเมื่อพิมพ์เสร็จถึงจุดสิ้นสุด


-1

ชื่อแทนสามารถและไม่สามารถดำเนินการตามมาตรฐาน stdin ...

ที่นี่เราสร้างเอาต์พุต 3 บรรทัด

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

จากนั้นเราจะส่งออกไปยัง stdin ของคำสั่ง sed เพื่อวางทั้งหมดในบรรทัดเดียว

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

หากเรากำหนดนามแฝงของคำสั่ง sed เดียวกัน

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

เราสามารถส่งออกไปยัง stdin ของนามแฝงและมันจะทำงานเหมือนกัน

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

ปัญหาเกิดขึ้นเมื่อเราพยายามกำหนด alias เป็นฟังก์ชั่น

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

การกำหนดนามแฝงเป็น funstion แบ่งท่อ

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

ประการแรกสิ่งนี้ไม่ตอบคำถาม - คุณอาจตอบคำถามผิดหรือเปล่า? ประการที่สองทำไมคุณถึงกำหนดฟังก์ชั่นภายในนามแฝง function oline() { sed -e ":a;N;\$!ba ;s?\n? ?g"; }คุณก็ควรจะทำ ประการที่สามawk -F '\n' 'ORS=" " { print } END { printf "\n"}'
รถคัน
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.