Positive and Negative Lookahead and Lookbehind in Python Regular Expressions
บางครั้งคุณต้องแก้ปัญหาประเภทนี้:
ค้นหาสตริง 'aaa' และแทนที่ด้วย
'!', แต่เฉพาะเมื่อหลังจาก
'aaa' มี 'x' อยู่ โดยที่ตัว
'x' นั้นไม่ถูกแทนที่ หากเรา
พยายามแก้ปัญหา 'แบบตรงไปตรงมา',
เราจะทำไม่ได้:
txt = 'aaax baaa'
res = re.sub('aaax', '!', txt)
print(res) # ได้ผลลัพธ์ '! baaa' แต่ต้องการ '!x baaa'
Lookahead
เพื่อแก้ปัญหา จำเป็นต้องมีวิธีบอกว่า
ไม่ควรแทนที่ 'x' ทำได้
โดยใช้วงเล็บพิเศษ (?= ),
ซึ่งเพียงแค่ "มองดู" แต่ไม่ดึงตัวอักษรนั้น
ไปด้วย
วงเล็บเหล่านี้เรียกว่า positive lookahead
(การมองไปข้างหน้าเชิงบวก) เป็นเชิงบวกเพราะ 'x'
(ในกรณีของเรา) ต้องมีอยู่ - เฉพาะตอนนั้น
การแทนที่จึงจะเกิดขึ้น
ลองใช้วงเล็บเหล่านี้เพื่อแก้ ปัญหาของเรา:
txt = 'aaax baaa'
res = re.sub('aaa(?=x)', '!', txt)
print(res) # ได้ผลลัพธ์ '!x aaab
นอกจากนี้ยังมี negative lookahead
(การมองไปข้างหน้าเชิงลบ)
- (?! ) - มันบอกในทางตรงกันข้าม
ว่าควรจะไม่มีบางสิ่ง ในตัวอย่าง
ถัดไป การแทนที่จะเกิดขึ้น เฉพาะเมื่อ
หลังจาก 'aaa' ไม่ใช่ 'x':
txt = 'aaax aaab'
res = re.sub('aaa(?!x)', '!', txt)
print(res) # ได้ผลลัพธ์ 'aaax !b'
Lookbehind
ในทำนองเดียวกัน มี positive
lookbehind (การมองย้อนหลังเชิงบวก) - (?<= ) ใน
ตัวอย่างถัดไป การแทนที่จะเกิดขึ้น เฉพาะ
เมื่อก่อน 'aaa' มี 'x' อยู่:
txt = 'xaaa'
res = re.sub('(?<=x)aaa', '!', txt)
print(res) # ได้ผลลัพธ์ 'x!'
และยังมี negative lookbehind (การมองย้อนหลังเชิงลบ)
- (?<! ) ในตัวอย่างถัดไป
การแทนที่จะเกิดขึ้น เฉพาะเมื่อก่อนหน้า
'aaa' ไม่มี 'x' อยู่:
txt = 'baaa'
res = re.sub('(?<!x)aaa', '!', txt)
print(res) # ได้ผลลัพธ์ 'b!'
โจทย์ฝึกปฏิบัติ
กำหนดสตริงซึ่งมีชื่อฟังก์ชัน:
txt = 'func1() func2() func3()'
ให้รับอาร์เรย์ของชื่อฟังก์ชันจากสตริง
กำหนดสตริงที่มีแท็ก:
txt = '<a href="" class="eee" id="zzz">'
ให้รับอาร์เรย์ของชื่อแอตทริบิวต์ของแท็กนี้
กำหนดสตริงที่มีตัวแปร:
txt = '$aaa $bbb $ccc xxxx'
ให้รับสตริงย่อยที่นำหน้าด้วย สัญลักษณ์ดอลลาร์