การส่งผ่านสองอาร์กิวเมนต์ไปยังคำสั่งโดยใช้ไพพ์


22

โดยปกติเราจะต้องผ่านการโต้แย้งเพียงครั้งเดียวเท่านั้น:

echo abc | cat
echo abc | cat some_file -
echo abc | cat - some_file

มีวิธีการผ่านสองข้อโต้แย้งหรือไม่? สิ่งที่ต้องการ

{echo abc , echo xyz} | cat
cat `echo abc` `echo xyz`

ฉันสามารถเก็บผลลัพธ์ทั้งสองไว้ในไฟล์ก่อนได้

echo abc > file1
echo xyz > file2
cat file1 file2

แต่ฉันอาจเขียนทับไฟล์โดยไม่ตั้งใจซึ่งไม่เป็นไร นี่จะเป็นสคริปต์แบบไม่โต้ตอบ โดยพื้นฐานแล้วฉันต้องการวิธีส่งผลลัพธ์ของคำสั่งสองคำสั่งไปยังcatโดยไม่ต้องเขียนลงไฟล์


อัปเดต: ขออภัยตัวอย่างนี้ปิดบังปัญหา ในขณะที่{ echo abc ; echo xyz ; } | catดูเหมือนจะทำงานออกเป็นเนื่องจากการechos catไม่

ตัวอย่างที่ดีกว่าคือ{ cut -f2 -d, file1; cut -f1 -d, file2; } | paste -d,สิ่งใดที่ใช้ไม่ได้ตามที่คาดไว้

กับ

file1:
a,b
c,d

file2:
1,2
3,4

ผลลัพธ์ที่คาดหวังคือ:

b,1
d,3

มีมติ:

ใช้การทดแทนกระบวนการ :cat <(command1) <(command2)

อีกทางเลือกหนึ่งให้สร้างชื่อ pipes โดยใช้mkfifo:

mkfifo temp1
mkfifo temp2
command1 > temp1 &
command2 > temp2 &
cat temp1 temp2

สง่างามน้อยลงและ verbose มากขึ้น แต่ใช้งานได้ดีตราบใดที่คุณแน่ใจว่า temp1 และ temp2 ไม่มีอยู่ก่อนมือ


1
นี่ทำให้ฉันเกาหัว คุณต้องการไพพ์สองคำสั่งต่างกันในแมวตัวเดียวหรือไม่?
606723

2
คุณรู้หรือไม่ว่า "piping" และ "arguments" เป็นสองแนวคิดที่ไม่เกี่ยวข้องกันใช่มั้ย
Ignacio Vazquez-Abrams

@Ignacio เอ่อ ... ฉันไม่คุ้นเคยกับ Linux ดังนั้นฉันจึงไม่ทราบถึงความแตกต่าง ฉันคิดเสมอว่าการไพพ์หมายความว่าจะใช้ผลลัพธ์ก่อนหน้าเป็นอาร์กิวเมนต์ สนใจที่จะสอนฉัน
goweon

@firebat no หมายถึงไพพ์ใช้ stdout ของคำสั่งก่อนหน้าเป็นอินพุตมาตรฐานของคำสั่งถัดไป คุณยังสามารถมีข้อโต้แย้งซึ่งเป็นแนวคิดที่แตกต่าง
Rich Homolka

นอกจากนี้เท่าที่ข้อความอัปเดตของคุณผลลัพธ์มาจาก cat เพียงคุณต้องการข้อความที่ดูเหมือนแยกต่างหากกับ cat ซึ่งไม่สามารถทำได้เนื่องจากมีการจัดลำดับเป็นหนึ่งสตรีม
Rich Homolka

คำตอบ:


17

ฉันคิดว่าคุณต้องการ 'กระบวนการชดเชย' http://tldp.org/LDP/abs/html/process-sub.html นอกจากนี้ยังใช้งานได้กับ zsh แม้ว่าจะมีตัวเลือกเพิ่มเติมและไวยากรณ์อาจแตกต่างกัน

มันสร้างไฟล์เทียม ( /dev/fd/something) สำหรับการทดแทนแต่ละครั้ง มันมีประโยชน์ทีเดียว คำสั่งสามารถอ่านเป็นกระแสได้เท่านั้นซึ่งหมายความว่าไม่สามารถย้อนกลับไปมาด้วย fseek มันจำเป็นต้องอ่านมันเป็นสตรีมของไบต์เช่นไพพ์

ตัวอย่างของคุณทำงานเป็นกระบวนการทดแทน:

cat <(echo abc) <(echo xyz)
paste -d, <(cut -f2 -d, file1) <(cut -f1 -d, file2)

คิดว่ามันเป็นเครื่องมือในการใช้กระบวนการและให้มันหลอกว่าเป็นไฟล์ที่ไม่มีไฟล์ชั่วคราว

(จากคำตอบก่อนหน้าของฉัน)


2

วงเล็บปีกกาสิ่งที่ใช้งานได้จริงเพราะผู้ประกอบการท่อจะเชื่อมต่อเอาท์พุทมาตรฐานของคำสั่งจัดกลุ่มเข้ากับอินพุตมาตรฐานของที่สาม

คุณสามารถบอกได้ว่างานพิมพ์นั้นไม่ได้มาจาก echos โดยการรันคำสั่งใด ๆ ที่ไม่ได้ใช้อินพุตมาตรฐานเช่น{ echo 1; echo 2;} | echo 3จะพิมพ์ 3 ซึ่งตรงข้ามกับ 1 \ n2 \ n3

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

คุณสามารถใช้mktempเพื่อสร้างไฟล์ชั่วคราวที่ไม่ซ้ำกันหรือmkfifoเพื่อสร้างไฟล์ไปป์ FIFO


ขอบคุณมากสำหรับคำตอบของคุณฉันค้นหาไปหลายวันเพื่อหาวิธีแก้ปัญหานี้
Saeed Falsafin

2

ฉันชอบ xargs เป็นตัวอย่างฉันต้องการหาขนาดของ mysql data dir ใต้ / usr / local

osx: ผู้ใช้ท้องถิ่น $ pwd
/ usr / local
osx: ผู้ใช้ท้องถิ่น $ ls | grep mysql
MySQL
MySQL-5.0.51a-osx10.5-x86_64
MySQL-5.0.51b-osx10.5-x86_64
MySQL-5.1.39-osx10.5-x86_64
MySQL-5.6.17-osx10.7-x86_64
os x: ผู้ใช้ท้องถิ่น $ ls | grep mysql | sudo xargs du -sh
MySQL 4.0K
2.8G mysql-5.0.51a-osx10.5-x86_64
 10G mysql-5.0.51b-osx10.5-x86_64
 25G mysql-5.1.39-osx10.5-x86_64
753M mysql-5.6.17-osx10.7-x86_64
osx: ผู้ใช้ท้องถิ่น $ 

xargs

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