ตัวอย่างที่ดีของคำสั่ง piping ด้วยกันคืออะไร?


33

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

cat whatever.txt | less

ฉันรู้สึกว่าไม่ใช่ตัวอย่างที่ดีที่สุดนั่นก็เพราะมีเพียงขั้นตอนเดียว การใช้งานที่ดี|คืออะไร

ตัวอย่างที่ฉันจะนำเสนอจะใช้โปรแกรมที่มีเอาท์พุตของตัวเองที่สามารถทำงานได้อย่างอิสระจากนั้นแสดงให้เห็นถึงการรวมเข้าด้วยกัน


3
ตัวอย่างของคุณไม่ดีเท่าไร - โดยทั่วไปแล้วเป็นการเสนอชื่อสำหรับรางวัลการใช้งานที่ไร้ประโยชน์ของแมว
maxschlepzig

@maxschlepzig ไม่ว่าคุณจะผิด แต่คุณก็ไม่ได้ช่วยอะไรมาก คุณไม่จำเป็นต้องทำเช่นcatนั้นเพราะless whatever.txtทำงานได้ดี
Bora M. Alper

คำตอบ:


34

ฉันจะแนะนำคุณผ่านตัวอย่างที่ค่อนข้างซับซ้อนโดยอ้างอิงจากสถานการณ์ในชีวิตจริง

ปัญหา

สมมติว่าคำสั่งconkyหยุดการตอบสนองบนเดสก์ท็อปของฉันและฉันต้องการฆ่าด้วยตนเอง ฉันรู้ว่านิด ๆ หน่อย ๆ ของ Unix kill <PID>เพื่อให้ฉันรู้ว่าสิ่งที่ผมต้องทำคือการดำเนินการคำสั่ง เพื่อดึงข้อมูล PID ฉันสามารถใช้psหรือtopเครื่องมืออะไรก็ได้ที่ Unix ของฉันแจกจ่ายให้ฉัน แต่ฉันจะทำสิ่งนี้ในคำสั่งเดียวได้อย่างไร

ตอบ

$ ps aux | grep conky | grep -v grep | awk '{print $2}' | xargs kill

การปฏิเสธความรับผิด: คำสั่งนี้จะทำงานเฉพาะในบางกรณี อย่าคัดลอก / วางในเทอร์มินัลของคุณและเริ่มใช้มันอาจทำให้กระบวนการไม่น่าสงสัย แต่เรียนรู้วิธีการที่จะสร้างมันขึ้นมา

มันทำงานอย่างไร

1- ps aux

คำสั่งนี้จะส่งออกรายการกระบวนการที่กำลังทำงานอยู่และข้อมูลบางอย่างเกี่ยวกับพวกเขา ข้อมูลที่น่าสนใจคือมันจะส่งออก PID ของแต่ละกระบวนการในคอลัมน์ที่ 2 นี่คือสารสกัดจากผลลัพธ์ของคำสั่งในกล่องของฉัน:

$ ps aux
 rahmu     1925  0.0  0.1 129328  6112 ?        S    11:55   0:06 tint2
 rahmu     1931  0.0  0.3 154992 12108 ?        S    11:55   0:00 volumeicon
 rahmu     1933  0.1  0.2 134716  9460 ?        S    11:55   0:24 parcellite
 rahmu     1940  0.0  0.0  30416  3008 ?        S    11:55   0:10 xcompmgr -cC -t-5 -l-5 -r4.2 -o.55 -D6
 rahmu     1941  0.0  0.2 160336  8928 ?        Ss   11:55   0:00 xfce4-power-manager
 rahmu     1943  0.0  0.0  32792  1964 ?        S    11:55   0:00 /usr/lib/xfconf/xfconfd
 rahmu     1945  0.0  0.0  17584  1292 ?        S    11:55   0:00 /usr/lib/gamin/gam_server
 rahmu     1946  0.0  0.5 203016 19552 ?        S    11:55   0:00 python /usr/bin/system-config-printer-applet
 rahmu     1947  0.0  0.3 171840 12872 ?        S    11:55   0:00 nm-applet --sm-disable
 rahmu     1948  0.2  0.0 276000  3564 ?        Sl   11:55   0:38 conky -q

2- grep conky

ฉันสนใจเฉพาะในกระบวนการหนึ่งดังนั้นฉันใช้เพื่อหารายการที่สอดคล้องกับโปรแกรมของฉันgrepconky

$ ps aux | grep conky
 rahmu     1948  0.2  0.0 276000  3564 ?        Sl   11:55   0:39 conky -q
 rahmu     3233  0.0  0.0   7592   840 pts/1    S+   16:55   0:00 grep conky

3- grep -v grep

ดังที่คุณเห็นในขั้นตอนที่ 2 คำสั่งpsแสดงผลgrep conkyกระบวนการในรายการ (เป็นกระบวนการที่ทำงานหลังจากทั้งหมด) grep -v grepเพื่อที่จะกรองมันก็สามารถทำงานได้ ตัวเลือก-vบอกgrepให้จับคู่ทุกบรรทัดยกเว้นบรรทัดที่มีรูปแบบ

$ ps aux | grep conky | grep -v grep
 rahmu     1948  0.2  0.0 276000  3564 ?        Sl   11:55   0:39 conky -q

NB: ฉันชอบที่จะรู้วิธีการทำขั้นตอนที่ 2 และ 3 ในการgrepโทรครั้งเดียว

4- awk '{print $2}'

ตอนนี้ฉันแยกกระบวนการเป้าหมายออกแล้ว ฉันต้องการดึง PID ของมัน ในคำอื่น ๆ ฉันต้องการดึงคำที่ 2 ของผลลัพธ์ โชคดีสำหรับฉันส่วนใหญ่ (ทั้งหมดหรือไม่) ที่ทันสมัยที่สุดจะให้บางรุ่นawkภาษาสคริปต์ที่ไม่น่าแปลกใจกับข้อมูลแบบตาราง print $2งานของเราจะกลายเป็นเรื่องง่ายเหมือน

$ ps aux | grep conky | grep -v grep | awk '{print $2}'
 1948

5- xargs kill

ฉันมี PID killทั้งหมดที่ฉันต้องการก็คือการผ่านไป xargsการทำเช่นนี้ผมจะใช้

xargs killจะอ่านจากอินพุต (ในกรณีของเราจากไพพ์) สร้างคำสั่งประกอบด้วยkill <items>( <items>เป็นสิ่งที่มันอ่านจากอินพุต) จากนั้นเรียกใช้คำสั่งที่สร้างขึ้น kill 1948ในกรณีของเราก็จะดำเนินการ ภารกิจเสร็จสมบูรณ์.

คำพูดสุดท้าย

โปรดทราบว่าขึ้นอยู่กับรุ่นของยูนิกซ์ที่คุณกำลังใช้งานบางโปรแกรมอาจทำงานแตกต่างกันเล็กน้อย (ตัวอย่างเช่นpsอาจส่งออก PID ในคอลัมน์ $ 3) หากสิ่งที่ดูเหมือนว่าผิดหรือแตกต่างกันอ่านเอกสารของผู้ขาย (หรือดีกว่าmanหน้า) ระวังด้วยเพราะท่อยาวอาจเป็นอันตรายได้ อย่าทำให้สมมติฐานใด ๆ โดยเฉพาะอย่างยิ่งเมื่อใช้คำสั่งเช่นหรือkill rmตัวอย่างเช่นหากมีผู้ใช้อื่นชื่อ 'conky' (หรือ 'Aconkyous') คำสั่งของฉันอาจฆ่ากระบวนการทำงานทั้งหมดของเขาด้วยเช่นกัน!

สิ่งที่ฉันพูดคือระวังโดยเฉพาะอย่างยิ่งสำหรับท่อยาว มันจะดีกว่าเสมอในการสร้างมันแบบโต้ตอบตามที่เราทำที่นี่มากกว่าตั้งสมมติฐานและรู้สึกเสียใจในภายหลัง


NB: ฉันชอบที่จะรู้วิธีที่จะทำตามขั้นตอนที่ 2 และ 3 ในการโทร grep เดียว -> grep "conky -q" :)
Wolfy

3
จริงๆแล้วนี่เป็นตัวอย่างที่ไม่ดีอย่างที่คุณทำได้kill $(pgrep conky)
แพทริค

5
ฉันรู้ว่ามันสายไปแล้ว แต่คุณสามารถทำให้มันง่ายขึ้นไปอีกpkill conky
strugee

2
"" "NB: ฉันชอบที่จะรู้วิธีการทำตามขั้นตอนที่ 2 และ 3 ในการเรียกใช้ grep ครั้งเดียว" "" แทนที่จะใช้ "aux" ให้ใช้ "-o pid, comm" - นี่ยังพกพาได้มากกว่าเพราะเป็น POSIX เข้ากัน ด้วยวิธีนี้กระบวนการ grep จะแสดงเป็น "grep" แทนที่จะเป็น "grep conky" ดังนั้นจึงไม่ตรงกับตัวเอง
Random832

2
NB: ฉันชอบที่จะรู้วิธีการทำขั้นตอนที่ 2 และ 3 ในการgrepโทรครั้งเดียว grep [c]onkyคือสิ่งที่คุณกำลังมองหา
AlexT

15

สิ่งที่ฉันชอบคืออันนี้:

youtube-dl $1 -q -o - | ffmpeg -i - $2

ดาวน์โหลดวิดีโอจาก URL ของ YouTube ได้รับการส่งผ่านไปตามและเอาท์พุทเป็นไฟล์ที่ได้รับจาก$1 $2หมายเหตุว่าไฟล์อยู่อย่างเงียบ ๆ-qออกไป STDOUT -o -, ประปา ffmpeg และใช้เป็น input -i -โดยมี

โดยเฉพาะอย่างยิ่งสำหรับมือใหม่ที่ใช้ linux นี่อาจเป็นตัวอย่างที่ชัดเจนว่าทำไมบรรทัดคำสั่งจึงมีประโยชน์และทำให้การทำงานง่ายกว่าการใช้เครื่องมือ GUI ฉันไม่แน่ใจว่าจะใช้เวลานานเท่าใดในการดาวน์โหลดวิดีโอจาก youtube และแปลงเสียงเป็น mp3 บรรทัดข้างต้นสามารถทำได้ในไม่กี่วินาที


3
youtube-dl มีตัวเลือกให้บันทึกเสียงเท่านั้น คำสั่งปกติของฉันนี้ที่ URL ที่มาใน youtube-dl --extract-audio --audio-format mp3 -a -stdin: ยังคงเป็นตัวอย่างที่ดี แต่มีวิธีที่ง่ายกว่าที่จะทำ (เรียกว่า ffmpeg ภายใน)
Brigand

3
@FakeRainBrigand: ฮ่าฮ่ารู้ดี! แต่ฉันมีทางเลือกที่ไม่ควรสร้างใน: youtube-dl $1 -q -o - | mplayer -เล่นวิดีโอภายใน mplayer โดยตรง ฉันใช้คำสั่งนั้นจากแล็ปท็อปของฉันเพื่อบอกเซิร์ฟเวอร์ของฉัน (ซึ่งเชื่อมต่อกับทีวี) เพื่อเล่นวิดีโอ ฉันต้องผนวก-display :0.0 -geometry 400x300+1200+200เพื่อให้หน้าต่าง mplayer ปรากฏบนหน้าจอที่ถูกต้อง
Baarn

9

การใช้งานทั่วไป (อ่าน: วิธีที่ฉันใช้บ่อยที่สุด) คือเมื่อฉันด้วยเหตุผลบางอย่างฉันต้องเรียกใช้ข้อมูลบางอย่างผ่านเครื่องมือหลายอย่างเพื่อดำเนินงานการประมวลผลที่แตกต่างกัน

ดังนั้นฉันจึงบอกว่าการใช้ท่อเป็นเหมือนกาวในการประกอบหลายหน่วยการสร้าง (เครื่องมือ UNIX ที่แตกต่างกัน) เข้าด้วยกัน เหมือน Ulrich กล่าวsortและuniqเป็นบททั่วไป

หากคุณต้องการเน้นการใช้ท่อนี้คุณสามารถทำได้เช่นเริ่มต้นด้วย: "เฮ้หลักสูตรนี้มีลิงค์ไปยังไฟล์ PDF ที่น่าสนใจหลายฉบับด้วยเอกสารและบันทึกการบรรยาย แต่บางส่วนสามารถทำซ้ำได้ฉันสามารถ ทำสิ่งนี้โดยอัตโนมัติหรือไม่ "

จากนั้นคุณสามารถแสดงให้เห็นว่าlynx --dump --listonlyได้รับรายการลิงก์อย่างไรgrepสามารถกรองลิงก์ที่ลงท้ายด้วย.pdfวิธีcolrmหรือsedกำจัดตัวเลขที่lynxเขียนไปยังแต่ละ URL ได้อย่างไรอย่างไรsortและuniqสามารถกำจัดรายการที่ซ้ำกันได้อย่างไรและสุดท้ายwget -i -จะใช้เพื่อดึงข้อมูล ไฟล์ (ใช้--waitเป็นอ่อนโยนบนเซิร์ฟเวอร์แน่นอน)

ฉันกลัวว่านี่เป็นตัวอย่างที่ซับซ้อน ในทางกลับกันมันอาจช่วยแสดงพลังของท่อเมื่อคุณเพิ่งวางท่อและให้เปลือกใช้งานได้ทันที


2
คุณสามารถใช้sort -uในcoreutils ของ GNU ได้เช่นกัน
Teresa e Junior

2

ผมไม่ทราบว่าเกี่ยวกับการที่ดี แต่ท่อผ่านที่จะเป็นหนึ่งของการใช้งานที่พบมากที่สุดมีอาจจะตามมาด้วยgrep wc -l(ใช่grepมี-cสวิตช์ที่รู้จักกันน้อย)

บททั่วไปอื่นคือ| sort | uniqถ้าเพียงเพราะuniqต้องการอินพุตที่จะเรียงลำดับ


คนส่วนใหญ่ชอบ... | sort -uถ้ามี!

2

ไม่ใช่ว่าคุณต้องการมันสำหรับตัวอย่างนี้ แต่:

$ ps aux | grep -v grep | grep conky

... การกลับคำสั่งของ greps จะคงไว้ซึ่ง colorization แต่มีประสิทธิภาพน้อยกว่ามาก สันนิษฐานว่าเป็นรายการขนาดใหญ่สีไม่สำคัญ

นอกจากนี้หน้าเว็บนี้แนะนำ:

https://stackoverflow.com/questions/9375711/more-elegant-ps-aux-grep-v-grep

> Johnsyweb ตอบวันที่ 21 ก.พ. 12 เวลา 10:31 น
> เคล็ดลับปกติคือ:
> ps aux | grep '[t] erminal'
> สิ่งนี้จะจับคู่บรรทัดที่มีเทอร์มินัลซึ่ง grep '[t] erminal' ไม่ได้!
> มันยังใช้งานได้กับ Unix หลายรสชาติ

... แต่นั่นจะไม่ทำงานหากคุณกำลังมองหาจดหมายฉบับเดียว (เช่นกระบวนการ 'X')


2

ในที่สุดฉันก็จะแบ่งปันความยุ่งเหยิงของ oneliner ที่ฉันทำเมื่อประมาณหนึ่งปีครึ่งที่ผ่านมา ...

while read in; do host "$in"; done < sites.txt | grep -iv "GOOGLE" | grep -E '1\.2\.3\.4|5\.6\.7\.8' | sed -e 's/has\ address\ 216.70.91.72//' | sed -e 's/has\ address\ 94.23.33.92//' | while read sites; do curl -sL -w "%{http_code} %{url_effective}\\n" "$sites" -o /dev/null; done | grep -ivE '4.*|5.*' | sed -e 's/200//' | sed -e 's/HTTP/http/'

มัน...

  1. อ่าน sites.txt
  2. เรียกใช้ "โฮสต์" ในแต่ละครั้ง (ในการเข้าใจถึงปัญหาหลังขุด + สั้นจะทำให้เรื่องนี้ง่ายขึ้นเป็นตัน)
  3. ลบบรรทัดที่มี "GOOGLE" - นี่คือเรคคอร์ด mx
  4. รับบรรทัดที่มีหนึ่งในสอง IP
  5. รับรหัสสถานะ http จากแต่ละไซต์ในรายการ
  6. ลบไซต์ที่ส่งคืน 4xx หรือ 5xx
  7. ดึง "200" ออกจากไซต์ที่ส่งคืนมา
  8. แทนที่ "HTTP" ด้วย "http" - ความสวยงามหมดจดไม่มีเหตุผลจริง

สิ่งนี้สามารถทำได้ดีกว่ามากด้วยสคริปต์ Python เดียวฉันเดิมพัน


เอ่อ ... ฉันไม่แน่ใจว่านี่จะเป็นตัวอย่างที่สะอาดและง่ายที่สุดสำหรับการอธิบายการไปยังมือใหม่;)
Erathiel

2
คำถามของฉันคืออะไรจุดประสงค์ของมันคืออะไร?
ADTC

ฉันมีไฟล์ที่เต็มไปด้วยโดเมนและฉันต้องการดูว่าพวกเขาอยู่ในหนึ่งในสองเซิร์ฟเวอร์ของฉันหรือไม่ สิ่งนี้อ่านไฟล์ทำ "host" และล้างเอาต์พุตนั้นจากนั้นทำการร้องขอเพื่อดูว่ามันส่งคืนข้อผิดพลาด 4xx หรือ 5xx หรือไม่ ถ้ามันเป็นเช่นนั้นก็จะทิ้งโดเมน; ถ้าไม่มันออกมาและฉันใส่ไว้ในไฟล์อื่น
ฟอกหนัง

1

นี่เป็นสิ่งแรกที่ฉันนึกถึง ...

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

mysqldump <options> > mydb.dump

ที่จะให้สคริปต์ sql ที่ไม่บีบอัด เพื่อประหยัดพื้นที่คุณสามารถบีบอัดด้วย bzip2

bzip2 mydb.dump

หรือคุณสามารถทำทั้งสองอย่างในขั้นตอนเดียว:

mysqldump <options> | bzip2 > mydb.dump.bz2

ในตัวอย่างนี้ด้านบน stdout จากmysqldumpถูกไพพ์ไปยัง bzip2 ซึ่งจะมีการเปลี่ยนเส้นทางไปยังไฟล์


1
เพิ่มการดำเนินการย้อนกลับเช่นกัน: bzcat mydb.dump.bz2 | mysql <options>.
จัดการ

1

นี่คือตัวอย่างที่ฉันใช้ในงานหลายไพพ์ในคำสั่งเดียว สิ่งนี้ใช้ gawk เพื่อค้นหาบันทึกการสืบค้นทั่วไป MySQL ($ OFILE) และค้นหาการเข้าสู่ระบบที่ถูกปฏิเสธ จากนั้นเรียงลำดับรายการตามชื่อไปป์ที่ลิสต์นั้นเป็น uniq ซึ่งนับการเกิดขึ้นจากนั้นไปป์มันจะเรียงลำดับหนึ่งครั้งล่าสุดเพื่อเรียงลำดับรายการที่นับเป็นตัวเลข ...

gawk '{ for (x=1;x<=NF;x++) if ( $x~"Access" && $(x+4)~".*@.*") print $(x+4)}' $OFILE | sort | uniq -c | sort -n

1

ท่อทำงานได้ดีที่สุดกับตัวกรองและตัวแปล

find /usr/bin/ |                #produce 
sed 's:.*/::'  |                #translate: strip directory part
grep -i '^z'   |                #filter   : select items starting with z
xargs -d '\n' aFinalConsumer    #consume  

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


0

cat filename | less เป็นการใช้ท่ออย่างสาหัสเนื่องจากคุณสามารถทำได้ less filename

นี่คือตัวอย่างของ pips ที่ฉันใช้ทุกวัน (แต่อาจเป็นตัวอย่างที่ไม่ดี): ls -la | more -c

สกอตต์ฮอฟแมนและคำตอบ njsg เป็นตัวอย่างที่ดีกว่า



0

ดำเนินการนี้ในไดเรกทอรีใด ๆ ที่คุณต้องการมีการวิเคราะห์เรียงขนาดโฟลเดอร์ (จากนั้นเลื่อนลงด้วยปุ่ม END):

du -m| sort -n| less

Sortiert nach Ordnergrösse


0

นี่คือตัวอย่างที่ฉันใช้สำหรับตั้งค่าตัวแปร DISPLAY เมื่อ xauth ไม่ใช่ตัวเลือก ...

export DISPLAY=\`who am i |awk '{print $NF}' | sed 's/[()]//g'`":0.0"

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


0

การไพพ์คำสั่งคุณสามารถใช้งานได้ทุกที่ที่คุณรู้สึกว่าเอาต์พุตของคำสั่งแรกสามารถป้อนเป็นอินพุตต่อไป

ตัวอย่าง.

  1. ด้วยไฟล์ข้อความคุณสามารถส่งไฟล์ข้อความไปยัง grep เพื่อค้นหาบรรทัดข้อความที่ต้องการ จากนั้นคุณสามารถส่งออกไปยัง sed หรือ awk เพื่อปรับเปลี่ยนหรือพิมพ์บางส่วนของบรรทัด

cat example txt | grep {some_line} | awk {some_command}

  1. การทำงานกับกระบวนการคุณสามารถใช้ piping เพื่อส่งคำสั่งเพื่อฆ่ากระบวนการ

เป็นเพียงแนวคิดที่ว่าถ้าคุณรู้สึกว่าผลลัพธ์ของคำสั่งที่คุณวิ่งสามารถป้อนข้อมูลของคำสั่งอื่นที่คุณสามารถท่อพวกเขา

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