เมื่อโลภเทียบกับไม่โลภ
การทำซ้ำใน regex โดยค่าเริ่มต้นเป็นโลภ : พวกเขาพยายามจับคู่ตัวแทนให้มากที่สุดเท่าที่จะเป็นไปได้และเมื่อมันไม่ทำงานและต้องย้อนกลับพวกเขาพยายามจับคู่ตัวแทนที่น้อยลงในแต่ละครั้งจนกว่าจะจับคู่รูปแบบทั้งหมด พบ เป็นผลให้เมื่อการแข่งขันเกิดขึ้นในที่สุดการทำซ้ำโลภจะตรงกับตัวแทนมากที่สุด
ใน?
ฐานะที่เป็นปริมาณการทำซ้ำการเปลี่ยนแปลงพฤติกรรมนี้เป็นที่ไม่โลภเรียกว่าลังเล ( ในเช่น Java ) (และบางครั้ง "ขี้เกียจ") ในทางกลับกันการทำซ้ำนี้จะพยายามจับคู่reps น้อยที่สุดเท่าที่จะเป็นไปได้ก่อนและเมื่อสิ่งนี้ไม่ทำงานและต้องย้อนรอยพวกเขาจะเริ่มจับคู่หนึ่งครั้งต่อครั้ง เป็นผลให้เมื่อการแข่งขันเกิดขึ้นในที่สุดการทำซ้ำอย่างไม่เต็มใจจะจับคู่ให้น้อยที่สุดเท่าที่จะทำได้
อ้างอิง
ตัวอย่างที่ 1: จาก A ถึง Z
ลองเปรียบเทียบทั้งสองรูปแบบ: และA.*Z
A.*?Z
รับอินพุตต่อไปนี้:
eeeAiiZuuuuAoooZeeee
รูปแบบให้ผลลัพธ์ที่ตรงกันดังต่อไปนี้:
ก่อนอื่นเรามาดูกันว่าA.*Z
จะทำอย่างไร เมื่อมันจับคู่แรกA
แล้ว.*
ความโลภจะพยายามจับคู่ให้ได้มาก.
ที่สุดก่อน
eeeAiiZuuuuAoooZeeee
\_______________/
A.* matched, Z can't match
เนื่องจากZ
ไม่ตรงกัน backtracks เครื่องยนต์และ.*
ต้องตรงกันน้อยกว่าหนึ่ง.
:
eeeAiiZuuuuAoooZeeee
\______________/
A.* matched, Z still can't match
สิ่งนี้เกิดขึ้นอีกสองสามครั้งจนในที่สุดเราก็มาถึงสิ่งนี้:
eeeAiiZuuuuAoooZeeee
\__________/
A.* matched, Z can now match
ตอนนี้Z
สามารถจับคู่ได้ดังนั้นรูปแบบโดยรวมจึงตรงกัน:
eeeAiiZuuuuAoooZeeee
\___________/
A.*Z matched
ในทางตรงกันข้ามการทำซ้ำไม่เต็มใจในA.*?Z
การแข่งขันครั้งแรกไม่กี่.
ที่เป็นไปได้และจากนั้นการเพิ่มเติม.
ตามความจำเป็น สิ่งนี้อธิบายได้ว่าเหตุใดจึงพบการแข่งขันสองรายการในอินพุต
ต่อไปนี้เป็นภาพที่แสดงให้เห็นถึงสิ่งที่ทั้งสองรูปแบบตรงกัน:
eeeAiiZuuuuAoooZeeee
\__/r \___/r r = reluctant
\____g____/ g = greedy
ตัวอย่าง: ทางเลือก
ในแอปพลิเคชั่นจำนวนมากการจับคู่ทั้งสองในอินพุตด้านบนเป็นสิ่งที่ต้องการดังนั้นจึงใช้ลังเลใจ.*?
แทนโลภ.*
เพื่อป้องกันการโอเวอร์คล็อก อย่างไรก็ตามสำหรับรูปแบบนี้มีทางเลือกที่ดีกว่าคือการใช้คลาสอักขระเมื่อตะกี้
รูปแบบA[^Z]*Z
ยังพบการจับคู่สองแบบเดียวกันกับA.*?Z
รูปแบบสำหรับอินพุตด้านบน ( ดังที่เห็นใน ideone.com ) [^Z]
เป็นสิ่งที่เรียกว่าตัวละครคลาสเมื่อตะกี้ : มันตรงกับอะไร Z
แต่
ความแตกต่างที่สำคัญระหว่างสองรูปแบบคือประสิทธิภาพ: เนื่องจากเข้มงวดมากขึ้นคลาสอักขระที่ไม่ได้ใช้งานสามารถจับคู่ทางเดียวเท่านั้นสำหรับอินพุตที่กำหนด ไม่สำคัญว่าคุณใช้ตัวแก้ไขโลภหรือลังเลสำหรับรูปแบบนี้ ในความเป็นจริงในบางรสชาติคุณสามารถทำได้ดียิ่งขึ้นและใช้สิ่งที่เรียกว่า quantifier ที่เป็นเจ้าของซึ่งไม่ย้อนกลับเลย
อ้างอิง
ตัวอย่างที่ 2: จาก A ถึง ZZ
ตัวอย่างนี้ควรเป็นตัวอย่าง: มันแสดงให้เห็นว่ารูปแบบของคลาสตัวละครโลภลังเลและไม่ตรงกับที่ได้รับจากอินพุตเดียวกันต่างกันอย่างไร
eeAiiZooAuuZZeeeZZfff
นี่คือการจับคู่สำหรับอินพุตด้านบน:
นี่คือภาพที่แสดงให้เห็นถึงสิ่งที่พวกเขาจับคู่:
___n
/ \ n = negated character class
eeAiiZooAuuZZeeeZZfff r = reluctant
\_________/r / g = greedy
\____________/g
หัวข้อที่เกี่ยวข้อง
นี่คือลิงก์ไปยังคำถามและคำตอบเกี่ยวกับสแต็คโอเวอร์โฟลว์ที่ครอบคลุมบางหัวข้อที่อาจเป็นที่สนใจ
การทำซ้ำโลภครั้งหนึ่งอาจเกินความสามารถไปอีกอย่างหนึ่ง