วิธีการเชื่อมต่อ stdin และสตริง?


108

ฉันจะเชื่อม stdin เข้ากับสตริงได้อย่างไร?

echo "input" | COMMAND "string"

และรับ

inputstring

คำตอบ:


119

บิต hacky แต่นี่อาจจะเป็นทางที่สั้นที่สุดที่จะทำสิ่งที่คุณถามคำถาม (ใช้ท่อที่จะยอมรับstdoutจากecho "input"เป็นstdinในการประมวลผลคำสั่ง / อื่น:

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

เอาท์พุต:

inputstring

คุณพยายามทำภารกิจอะไรให้สำเร็จ? บริบทเพิ่มเติมช่วยให้คุณมีทิศทางมากขึ้นเกี่ยวกับโซลูชันที่ดีกว่า

อัปเดต - ตอบกลับความคิดเห็น:

@NoamRoss

วิธีที่เป็นสำนวนมากขึ้นในการทำสิ่งที่คุณต้องการคือ:

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

$(...)ไวยากรณ์เรียกว่าคำสั่งเปลี่ยนตัว กล่าวโดยย่อคือรันคำสั่งที่อยู่ใน subshell ใหม่และแทนที่stdoutเอาต์พุตเป็นตำแหน่งที่$(...)ถูกเรียกใช้ในพาเรนต์เชลล์ ดังนั้นคุณจะได้รับผล:

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

1
ขอบคุณ! ใช้งานได้ดี งานที่แน่นอนที่ฉันพยายามทำคือเอาสตริงจากคลิปบอร์ด (DOI) และนำหน้า URL ไปด้วยดังนั้นฉันจึงทำสิ่งนี้pbpaste | awk '{print "http://dx.doi.org/"$1}'และได้รับhttp://dx.doi.org/10.1098/rsif.2012.0125
Noam Ross

5
@ sampson-chen ฉันใช้'{print $0"string"}'เพื่อคว้าทุกสิ่ง
Roman Newaza

3
มันต่อท้ายstringทุกบรรทัดจริงๆ ลองecho 'input'\n'another line' | awk '{print $0"string"}'.
tomekwi

55

ใช้cat -อ่านจาก stdin และนำ$()ไปทิ้งขึ้นบรรทัดใหม่ต่อท้าย

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

อย่างไรก็ตามทำไมคุณไม่วางท่อและดึงเอาท์พุทของด้านซ้ายในการแทนที่คำสั่ง:

COMMAND "$(echo input)string"

1
นี่คือตัวอย่างที่ใช้ได้จริง: find ~ / other_program / lib -name "* .jar" | tr '\ n' ':' | echo "$ (cat -) ~ / java_app / class"
Ashwin Jayaprakash

2
สิ่งนี้ใช้ได้กับฉันใน bash แต่ใน zsh ฉันได้รับ "cat: -: Input / output error" มีความคิดอะไรที่ทำให้เกิดสิ่งนี้?
jaymmer - คืนสถานะโมนิกา

"COMMAND" ย่อมาจากโซลูชันและ "echo input" สำหรับกระบวนการที่ซับซ้อนมากขึ้น จำเป็นต้องใช้ "-" arg to cat ก็ต่อเมื่อมีไฟล์ args อื่นมิฉะนั้นจะเป็นค่าเริ่มต้น สิ่งที่คุณหมายถึงคือ: echo input | echo $ (cat) string
Denis Howe

46

ฉันมักจะใช้ไปป์ดังนั้นนี่จึงเป็นวิธีง่ายๆในการเติมคำนำหน้าและคำต่อท้าย stdin:

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

2
ขอบคุณ! นั่นเป็นตัวอย่างที่ยอดเยี่ยมมากในการใช้pipeและcat
Alex Ivasyuv

1
นี่น่าจะเป็นคำตอบที่ดีที่สุด
Chris Koston

1
ทำไมไม่เพียง: echo "my standard in" | echo -e "prefix\n$(cat -)\nsuffix"? หรือรุ่นที่อ่านได้มากขึ้น:echo "my standard in" | printf "%s\n%s\n%s\n" "prefix" "$(cat -)" "suffix"
MiniMax

1
@MiniMax เนื่องจากคำตอบทำงานได้ดีกับสตรีมจึงใช้ได้กับ stdin ขนาดใหญ่
anishpatel

1
@anishpatel เวอร์ชันของฉันก็ใช้ได้กับ stdin ขนาดใหญ่เช่นกัน ไม่แตกต่าง.
MiniMax

11

คุณสามารถทำได้ด้วย sed:

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

ในตัวอย่างของคุณ:

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

9

มีบางวิธีในการทำให้สำเร็จโดยส่วนตัวแล้วฉันคิดว่าสิ่งที่ดีที่สุดคือ:

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

อีกอย่างหนึ่งสามารถแทนที่ "$" (อักขระท้ายบรรทัด) ด้วย "string" ในคำสั่ง sed:

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

ทำไมฉันถึงชอบอดีต? เนื่องจากมันเชื่อมสตริงเข้ากับ stdin ทันทีตัวอย่างเช่นด้วยคำสั่งต่อไปนี้:

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

คุณจะได้รับผลลัพธ์แรกทันที:

input_one string

จากนั้น 5 วินาทีคุณจะได้รับเสียงสะท้อนอื่น ๆ :

input_two string

ในทางกลับกันการใช้ "sed" ก่อนอื่นจะดำเนินการกับเนื้อหาทั้งหมดของวงเล็บจากนั้นจึงให้เป็น "sed" ดังนั้นคำสั่ง

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

จะส่งออกทั้งสองบรรทัด

input_one string
input_two string

หลังจาก 5 วินาที

สิ่งนี้มีประโยชน์มากในกรณีที่คุณเรียกใช้ฟังก์ชันซึ่งใช้เวลานานในการดำเนินการให้เสร็จสมบูรณ์และต้องการอัปเดตเกี่ยวกับเอาต์พุตของฟังก์ชันอย่างต่อเนื่อง


อันที่จริงตัวเลือกsedยังประมวลผลอินพุตทุกบรรทัดทันที
tomekwi

สำหรับอินพุตบรรทัดเดียววิธีที่ง่ายที่สุดคืออินพุตเสียงสะท้อน | (อ่าน v; echo $ {v} string) นั่นคือเปลือกที่บริสุทธิ์ดังนั้นจึงไม่ต้องใช้กระบวนการพิเศษเช่น sed
Denis Howe

7

ฉันรู้ว่านี่ช้าไปสองสามปี แต่คุณสามารถทำได้ด้วยตัวเลือก xargs -J:

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

และเนื่องจากมันเป็น xargs คุณสามารถทำสิ่งนี้กับไฟล์หลายบรรทัดพร้อมกันได้ หาก 'ชื่อ' ไฟล์มีสามบรรทัดเช่น:

Adam
Bob
Charlie

คุณสามารถทำได้:

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

1
ดูดียกเว้น-Jดูเหมือนจะไม่เป็นมาตรฐาน / ทั่วไป บน Linux ( xargsเป็นส่วนหนึ่งของส่วนไหนGNU findutils) ฉันได้รับข้อผิดพลาด: xargs: invalid option -- 'J'นี่คือระบบใด
arielf

3
-Jมีไว้สำหรับเวอร์ชัน Mac สำหรับลินุกซ์-Iทำหน้าที่เดียวกัน
user2635263

1
ขอบคุณ! มีประโยชน์มาก. โปรดทราบว่าบน Linux เวอร์ชันที่เรียบง่ายนี้ก็ใช้งานได้เช่นกัน: cat names | xargs -I% echo "I like % because he is nice"IOW: ไม่จำเป็นต้องใช้-n 1( xargsเรียกechoหนึ่งครั้งต่อบรรทัดของอินพุตอย่างไรก็ตามโดย-Iนัย-L1) นอกจากนี้การอ้างถึงอาร์กิวเมนต์ที่แยกจากกันทั้งหมดดูเหมือนจะซ้ำซ้อน
arielf

3

คำสั่งที่คุณโพสต์จะใช้สตริง "input" ใช้เป็นสตรีม stdin ของ COMMAND ซึ่งจะไม่ให้ผลลัพธ์ที่คุณต้องการเว้นแต่ว่า COMMAND จะพิมพ์เนื้อหาของ stdin ก่อนจากนั้นจึงพิมพ์อาร์กิวเมนต์บรรทัดคำสั่งออกมา

ดูเหมือนว่าสิ่งที่คุณต้องการทำนั้นใกล้เคียงกับการแทนที่คำสั่งมากกว่า

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

ด้วยการแทนที่คำสั่งคุณสามารถมีบรรทัดคำสั่งเช่นนี้:

echo input `COMMAND "string"`

ขั้นแรกจะประเมิน COMMAND ด้วย "string" เป็นอินพุตจากนั้นขยายผลลัพธ์ของการดำเนินการคำสั่งนั้นไปยังบรรทัดโดยแทนที่สิ่งที่อยู่ระหว่างอักขระ "" "


และแน่นอน @NaomRoss เว้นแต่คุณจะต้องใช้ Bourne shell หรือมีเอกสาร "พกพา" ที่บ้าคลั่งอื่น ๆ คุณจะใช้การแทนที่คำสั่งสมัยใหม่เช่นecho input $(COMMAND "string")แทนที่จะใช้ backticks โชคดีทุกคน.
เชลล์เตอร์

1

แมวจะเป็นทางเลือกของฉัน: ls | cat - <(echo new line)


sed เป็นคำสั่งตามบรรทัดซึ่งจะไม่ทำงานหากท่อต้นน้ำไม่มีเอาต์พุตอะไร ..
clarkttfu

0

ยังใช้งานได้:

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

จะสร้างสตริงเช่น:

string 000
string 001
string 002
string 003
string 004

...

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.