Python regexes ที่ไม่โลภ


150

ฉันจะทำให้ python regex เป็น"(.*)"เช่นนั้นได้อย่างไรจากการ"a (b) c (d) e"จับคู่ python "b"แทน"b) c (d"

ฉันรู้ว่าฉันสามารถใช้"[^)]"แทนได้"."แต่ฉันกำลังมองหาโซลูชันทั่วไปที่ทำให้ regex ของฉันสะอาดขึ้นเล็กน้อย มีวิธีใดที่จะบอกงูหลามว่า "เฮ้จับคู่มันให้เร็วที่สุด"

คำตอบ:


209

คุณแสวงหาพลังทั้งหมด *?

จากเอกสารโลภและไม่ใช่โลภ

บ่นไม่โลภ*?, +?, ??หรือ{m,n}?[ ... ] การแข่งขันเป็นเล็ก ๆ น้อย ๆ ข้อความที่เป็นไปได้


จากการอ้างอิงของ Internet Archive ลิงค์ทั้งหมดที่ชี้ไปนั้นเป็นสำเนาของเอกสารโมดูลของ Python ดังนั้นลิงก์ของ Trey ก็ใช้งานได้เช่นกัน
spiffytech

2
ชื่อภาษาอังกฤษทั่วไปสำหรับสิ่งนี้*?คืออะไร?
เทรเวอร์บอยด์สมิ ธ

อักขระตัวแทน @Trevor Boyd Smith
Serge

3
สิ่งนี้เรียกว่าการคัดเลือกแบบ"ไม่โลภ"
brunetton

65
>>> x = "a (b) c (d) e"
>>> re.search(r"\(.*\)", x).group()
'(b) c (d)'
>>> re.search(r"\(.*?\)", x).group()
'(b)'

ตามเอกสาร :

ตัวระบุ ' *', ' +' และ ' ?' ล้วน แต่โลภมาก พวกเขาจับคู่ข้อความให้มากที่สุด บางครั้งพฤติกรรมนี้ไม่ต้องการ; หาก RE <.*>ตรงกับ ' <H1>title</H1>' มันจะจับคู่กับสตริงทั้งหมดไม่ใช่เฉพาะ ' <H1>' การเพิ่ม ' ?' หลังจากตัวระบุทำให้มันทำการแข่งขันแบบไม่โลภหรือไม่มาก ตัวละครน้อยที่สุดเท่าที่เป็นไปได้จะถูกจับคู่ การใช้.*?ในนิพจน์ก่อนหน้าจะจับคู่เฉพาะ ' <H1>'



5

อย่างที่คนอื่นพูดกันว่าใช้? โมดิฟายเออร์ใน * quantifier จะแก้ปัญหาเฉพาะหน้าของคุณได้ แต่ระวังคุณจะเริ่มหลงทางในพื้นที่ที่ regexes หยุดทำงานและคุณต้องใช้ parser แทน ตัวอย่างเช่นสตริง "(foo (bar)) baz" จะทำให้คุณมีปัญหา


5

การใช้การจับคู่ที่ไม่ร้ายนั้นเป็นการเริ่มต้นที่ดี แต่ฉันขอแนะนำให้คุณพิจารณาการใช้งานอื่น ๆ.*- แล้วเรื่องนี้ล่ะ?

groups = re.search(r"\([^)]*\)", x)

3

คุณต้องการให้ตรงกับ "(b)" หรือไม่ ทำตามที่ Zitrax และ Paolo แนะนำ คุณต้องการให้ตรงกับ "b" หรือไม่ ทำ

>>> x = "a (b) c (d) e"
>>> re.search(r"\((.*?)\)", x).group(1)
'b'

0

ในการเริ่มต้นฉันไม่แนะนำให้ใช้ "*" ใน regexes ใช่ฉันรู้ว่ามันเป็นตัวคั่นหลายตัวที่ใช้มากที่สุด แต่มันก็เป็นความคิดที่ไม่ดี นี่เป็นเพราะแม้ว่าจะตรงกับจำนวนการซ้ำซ้อนสำหรับตัวละครนั้น ๆ ก็ตาม "any" รวมถึง 0 ซึ่งโดยปกติแล้วจะเป็นสิ่งที่คุณต้องการจะโยนข้อผิดพลาดทางไวยากรณ์สำหรับไม่ยอมรับ แต่ฉันขอแนะนำให้ใช้+เครื่องหมายซึ่งตรงกับการทำซ้ำความยาวใด ๆ > 1. ยิ่งไปกว่านั้นจากสิ่งที่ฉันเห็นคุณกำลังติดต่อกับนิพจน์ที่วงเล็บที่มีความยาวคงที่ เป็นผลให้คุณสามารถใช้{x, y}ไวยากรณ์เพื่อระบุความยาวที่ต้องการโดยเฉพาะ

อย่างไรก็ตามหากคุณต้องการการทำซ้ำที่ไม่โลภผมขอแนะนำให้ปรึกษาผู้มีอำนาจ?ทั้งหมด สิ่งนี้เมื่อวางไว้หลังสุดของตัวระบุการทำซ้ำ regex ใด ๆ จะบังคับให้ส่วนนั้นของ regex ค้นหาข้อความจำนวนน้อยที่สุดเท่าที่จะเป็นไปได้

ที่ถูกกล่าวว่าฉันจะต้องระมัดระวังอย่างยิ่งกับ?มันเช่นไขควงโซนิคในดร. ใครมีแนวโน้มที่จะทำอย่างไรฉันควรจะใส่มัน "เล็กน้อย" สิ่งที่ไม่พึงประสงค์หากไม่ได้สอบเทียบอย่างระมัดระวัง ตัวอย่างเช่นหากต้องการใช้ตัวอย่างอินพุตของคุณก็จะระบุ((1)(หมายเหตุขาด rparen ที่สอง) เป็นการจับคู่

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