grep เฉพาะนัดแรกและหยุด


329

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

# grep -o -a -m 1 -h -r "Pulsanti Operietur" /path/to/directory

ผลตอบแทน:

Pulsanti Operietur
Pulsanti Operietur

บางที grep ไม่ใช่วิธีที่ดีที่สุดในการทำสิ่งนี้? คุณบอกฉันขอบคุณมาก

คำตอบ:


511

-m 1หมายถึงคืนการแข่งขันครั้งแรกในไฟล์ใดก็ตาม แต่มันจะยังคงค้นหาไฟล์อื่นต่อไป นอกจากนี้หากมีการจับคู่สองรายการขึ้นไปในบรรทัดเดียวกันทั้งหมดจะปรากฏขึ้น

คุณสามารถใช้head -1เพื่อแก้ปัญหานี้:

grep -o -a -m 1 -h -r "Pulsanti Operietur" /path/to/dir | head -1

คำอธิบายของแต่ละตัวเลือก grep:

-o, --only-matching, print only the matched part of the line (instead of the entire line)
-a, --text, process a binary file as if it were text
-m 1, --max-count, stop reading a file after 1 matching line
-h, --no-filename, suppress the prefixing of file names on output
-r, --recursive, read all files under a directory recursively

! น่ากลัว ขอบคุณ. btw - ข้อโต้แย้งอื่น ๆ ทั้งหมดที่จำเป็นในคำสั่งคืออะไร? และถ้าฉันไม่สามารถเป่ามันโดยบังเอิญ (ในกรณี)
Tim Kamm

2
ฉันไม่คิดว่าพวกเขามีความจำเป็น (ยกเว้น-rชัด) แต่พวกเขาไม่ควรเจ็บ (ฉันจะไม่ใช้-aแม้ว่า)
mvp

3
สิ่งที่ฉันต้องการ รูปแบบของฉันถูกพบสองครั้งในบรรทัดเดียวกันและgrep -m 1ส่งคืนทั้งสองกรณีเนื่องจากสิ่งนี้ |head -1แก้ไขมัน!
harperville

6
@Chris_Rands พฤติกรรมที่แน่นอนขึ้นอยู่กับเชลล์ที่คุณใช้งานอยู่หัวจะออกทันทีที่พบบรรทัดแรก grep จะออกในครั้งถัดไปที่พยายามเขียนหลังจากที่หัวหน้าออกไปแล้ว เชลล์บางตัวจะรอจนกระทั่งองค์ประกอบทั้งหมดของไพพ์ไลน์เสร็จสิ้นบางอันจะทำให้ไพพ์ทั้งหมดหยุดทำงานทันทีที่โปรแกรมสุดท้ายในไพพ์จบการทำงาน
puhlen

1
@ 3QN first not first from resultผมไม่เข้าใจความคิดเห็นของคุณ: คำตอบนี้พิมพ์การจับคู่ครั้งแรกในไฟล์ใดก็ได้และหยุด คุณคาดหวังอะไรอีก
mvp

31

คุณสามารถไพพ์grepผลลัพธ์เพื่อheadร่วมกับstdbuf stdbuf

โปรดทราบว่าเพื่อให้แน่ใจว่าจะหยุดหลังจากการแข่งขัน Nth คุณต้องใช้ stdbufเพื่อให้แน่ใจgrepว่าไม่ได้บัฟเฟอร์ผลลัพธ์:

stdbuf -oL grep -rl 'pattern' * | head -n1
stdbuf -oL grep -o -a -m 1 -h -r "Pulsanti Operietur" /path/to/dir | head -n1
stdbuf -oL grep -nH -m 1 -R "django.conf.urls.defaults" * | head -n1

เร็ว ๆ นี้ headใช้ 1 บรรทัดจะถูกยกเลิกและgrepจะได้รับSIGPIPEเนื่องจากยังคงส่งออกบางสิ่งไปยังท่อขณะที่headหายไป

สิ่งนี้สันนิษฐานว่าไม่มีชื่อไฟล์ที่มีการขึ้นบรรทัดใหม่


ฉันพยายามที่จะนำมาใช้ในการแก้ปัญหานี้เพื่อค้นหาในจำนวนมากของไฟล์ที่เก็บด้วย:xargs find . -name '*.gz' | xargs -I '{}' stdbuf -oL zgrep -al 'pattern' {} | head -n 1อย่างไรก็ตามสิ่งนี้ไม่ได้ยุติลงในนัดแรก คำแนะนำใด ๆ?
DKroot

1
จะไม่grepเป็น--line-bufferedตัวเลือกที่ป้องกัน buffer ค่าใช้จ่ายโดยไม่ต้องโทรสาธารณูปโภคเพิ่มเติม?
David

23

โปรแกรม grep-a-like ของฉันackมี-1ตัวเลือกที่หยุดเมื่อพบคู่แรกได้ทุกที่ รองรับการ-m 1ที่ @mvp อ้างถึงเช่นกัน ฉันใส่ไว้ในนั้นเพราะถ้าฉันค้นหาทรีของซอร์สโค้ดขนาดใหญ่เพื่อค้นหาสิ่งที่ฉันรู้ว่ามีอยู่ในไฟล์เดียวมันไม่จำเป็นที่จะต้องค้นหามันและต้องกด Ctrl-C


ดังนั้นคุณจะบอกว่าแอ๊เร็วกว่า grep? ฉันกังวลเกี่ยวกับปัจจัยความเร็วด้วยเช่นกัน
ทิม Kamm

1
แอ๊เร็วกว่า grep ขึ้นอยู่กับว่าคุณกำลังค้นหาอะไร โปรดทราบว่า ack เป็นเรื่องเกี่ยวกับการค้นหาซอร์สโค้ด หากคุณกำลังมองหาไฟล์ทั่วไปมันไม่ค่อยดีเท่าไหร่อย่างน้อยใน ack 1.x ไปอ่านเกี่ยวกับ ack และดูว่ามันอาจจะเหมาะกับความต้องการของคุณ
Andy Lester

2
ฉันเคยใช้ Ack มานานแล้ว แต่เพิ่งเปลี่ยนมาใช้The Silver searcherซึ่งฉันพบว่าเร็วกว่า Ack
guy.gc

ฉันเชื่อว่านี่ควรเป็นคำตอบเดียวเพราะ OP บอกว่าเขาต้องการมันด้วย grep แต่คำตอบอื่น ๆ ใช้ head (ทั้งสองงาน) แต่มีสภาพแวดล้อมแบบฝังตัว / สร้างขึ้นเองด้วยเครื่องมือน้อยที่สุดที่ grep เป็นเรื่องธรรมดาและ tail / หัวไม่ได้
Areeb Soo Yasir

มูลค่าการกล่าวขวัญว่าagอาจจะเร็ว แต่มันไม่ได้มี-1ตัวเลือกซึ่งจะเป็นประโยชน์ในกรณีนี้
JJA

4

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

grep -m 1 -r "Not caching" * | head -1

2

ซับเดี่ยวโดยใช้find:

find -type f -exec grep -lm1 "PATTERN" {} \; -a -quit

6
สิ่งนี้จะช้ามากเนื่องจากการค้นหาจะวางไข่สำเนาของ grep สำหรับทุกไฟล์ที่พบ grep -rทำงานได้เร็วขึ้นมาก - มีเพียงสำเนาเดียวเท่านั้นที่ทำการสำรวจเส้นทางไดเรกทอรี
mvp

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