ฉันต้องการ grep คู่ที่สั้นที่สุดและรูปแบบควรเป็นดังนี้:
<car ... model=BMW ...>
...
...
...
</car>
... หมายถึงอักขระใด ๆ และอินพุตมีหลายบรรทัด
ฉันต้องการ grep คู่ที่สั้นที่สุดและรูปแบบควรเป็นดังนี้:
<car ... model=BMW ...>
...
...
...
</car>
... หมายถึงอักขระใด ๆ และอินพุตมีหลายบรรทัด
คำตอบ:
คุณกำลังมองหาการจับคู่ที่ไม่โลภ (หรือขี้เกียจ) ในการรับการจับคู่ที่ไม่โลภในนิพจน์ทั่วไปคุณต้องใช้ตัวแก้ไข?
หลังตัวระบุ ตัวอย่างเช่นคุณสามารถเปลี่ยนไป.*
.*?
โดยค่าเริ่มต้นgrep
ไม่รองรับการดัดแปลงที่ไม่ใช่โลภ แต่คุณสามารถใช้grep -P
เพื่อใช้ไวยากรณ์ของ Perl
.
จับคู่บรรทัดใหม่นั้นเรียกว่าDOTALLหรือโหมดบรรทัดเดียว Ruby เป็นเพียงหนึ่งเดียวที่เรียกมันว่าหลายสาย ในรสชาติอื่น ๆmultilineเป็นโหมดที่อนุญาตให้จุดยึด ( ^
และ$
) จับคู่ที่ขอบเขตของเส้น Ruby ไม่มีโหมดที่เทียบเท่ากันเพราะใน Ruby พวกเขาทำงานเช่นนั้นเสมอ
-P
เป็นสิ่งใหม่ที่สมบูรณ์แบบสำหรับฉันฉันมีความสุขไปหลายปีและใช้เพียง-E
... หลายปีที่สูญเปล่า! - หมายเหตุถึงตัวเอง: อ่านหน้าคนเป็นสิ่งปกติ (มากขึ้น!) คุณจะไม่แยกย่อยสวิตช์และตัวเลือกมากพอ
grep
ไม่รองรับ-P
แต่ถ้าคุณใช้egrep
คุณสามารถใช้.*?
รูปแบบเพื่อให้ได้ผลลัพธ์เดียวกัน egrep -o 'start.*?end' text.html
-P
แต่-E
จะเรียกegrep
ดังนั้นการ.*?
ทำงานที่แนะนำก็ใช้ได้
จริงงานเฉพาะใน.*?
perl
ฉันไม่แน่ใจว่าไวยากรณ์ grep Extended regexp ที่เทียบเท่าจะเป็นอย่างไร โชคดีที่คุณสามารถใช้ไวยากรณ์ Perl กับ grep ดังนั้นgrep -P
จะทำงาน แต่grep -E
ซึ่งegrep
จะไม่ทำงาน (มันจะโลภ)
ดูเพิ่มเติมที่: http://blog.vinceliu.com/2008/02/non-greedy-regular-expression-matching.html
grep -P
ไม่ทำงานใน GNU grep 2.9 - เพียงแค่พยายามมัน (มันไม่ได้ผิดพลาดเพียงเงียบ ๆ ไม่ได้ใช้?
Intertestly ไม่ไม่ได้. ไม่ได้ระดับเช่น:env|grep '[^\=]*\='
grep -P
ตัวเลือกหรือpgrep
คำสั่งในดาร์วิน / OS X 10.8 Mountain Lion แต่ใช้egrep
งานได้ดี
pgrep
คำสั่งในกล่อง OS X 10.9 ของฉัน แต่เป็นโปรแกรมที่แตกต่างอย่างสิ้นเชิงโดยมีวัตถุประสงค์คือ "ค้นหาหรือกระบวนการสัญญาณตามชื่อ"
grep ของฉันที่ทำงานหลังจากลองสิ่งต่าง ๆ ในหัวข้อนี้:
echo "hi how are you " | grep -shoP ".*? "
ตรวจสอบให้แน่ใจว่าคุณต่อท้ายช่องว่างในแต่ละบรรทัดของคุณ
(Mine เป็นบรรทัดโดยการค้นหาบรรทัดเพื่อคายคำ)
-shoP
ดีช่วยในการจำ :)
echo "bbbbb" | grep -shoP 'b.*?b'
เป็นประสบการณ์การเรียนรู้เล็กน้อย สิ่งเดียวที่ทำงานสำหรับฉันในแง่ของความขี้เกียจอย่างชัดเจนเช่นกัน
grep
สำหรับการแข่งขันที่ไม่โลภในgrep
คุณสามารถใช้คลาสตัวละครที่ถูกทำให้ไร้ผล กล่าวอีกนัยหนึ่งพยายามหลีกเลี่ยงสัญลักษณ์แทน
ตัวอย่างเช่นหากต้องการดึงลิงก์ทั้งหมดไปยังไฟล์ jpeg จากเนื้อหาของหน้าคุณต้องใช้:
grep -o '"[^" ]\+.jpg"'
หากต้องการจัดการกับหลายบรรทัดให้ไพพ์อินพุตผ่านxargs
ก่อน ripgrep
เพื่อประสิทธิภาพในการใช้งาน
คำตอบสั้น ๆ คือการใช้นิพจน์ทั่วไปถัดไป:
(?s)<car .*? model=BMW .*?>.*?</car>
คำตอบที่ซับซ้อนมากขึ้นคือ:
(?s)<([a-z\-_0-9]+?) .*? model=BMW .*?>.*?</\1>
สิ่งนี้จะทำให้สามารถจับคู่ car1 และ car2 ในข้อความต่อไปนี้
<car1 ... model=BMW ...>
...
...
...
</car1>
<car2 ... model=BMW ...>
...
...
...
</car2>
ขออภัยฉันมาสาย 9 ปี แต่สิ่งนี้อาจใช้ได้กับผู้ชมในปี 2020
"Hello my name is Jello"
ดังนั้นสมมติว่าคุณมีเส้นเหมือน ตอนนี้คุณต้องการค้นหาคำที่ขึ้นต้น'H'
และลงท้ายด้วย'o'
จำนวนอักขระใด ๆ และเราไม่ต้องการบรรทัดที่เราต้องการคำ ดังนั้นเราจึงสามารถใช้การแสดงออก:
grep "H[^ ]*o" file
นี่จะคืนคำทั้งหมด วิธีการทำงานของมันคือ: มันจะอนุญาตให้ตัวละครทุกตัวแทนที่จะเป็นตัวอักษรเว้นวรรคในระหว่างนี้วิธีที่เราสามารถหลีกเลี่ยงคำหลายคำในบรรทัดเดียวกัน
ตอนนี้คุณสามารถแทนที่อักขระช่องว่างด้วยอักขระอื่น ๆ ที่คุณต้องการ สมมติว่าบรรทัดแรกคือ"Hello-my-name-is-Jello"
จากนั้นคุณสามารถหาคำโดยใช้นิพจน์:
grep "H[^-]*o" file
ฉันรู้ว่ามันเป็นบิตโพสต์ที่ตายแล้ว แต่ฉันเพิ่งสังเกตเห็นว่างานนี้ มันลบทั้งการทำความสะอาดและการล้างข้อมูลออกจากฉัน
> grep -v -e 'clean\-\?up'
> grep --version grep (GNU grep) 2.20