จับคู่ยูนิโค้ดใน regexes ของ ply

ฉันกำลังจับคู่ตัวระบุ แต่ตอนนี้ฉันมีปัญหา: ตัวระบุของฉันได้รับอนุญาตให้มีอักขระ Unicode ดังนั้นวิธีการทำแบบเก่าจึงไม่เพียงพอ:

t_IDENTIFIER = r"[A-Za-z](\\.|[A-Za-z_0-9])*"

ในตัวแยกวิเคราะห์ ภาษามาร์กอัปของฉัน ฉันจับคู่อักขระ Unicode โดยอนุญาตให้ใช้อักขระทั้งหมด ยกเว้นอักขระที่ฉันใช้อย่างชัดเจน เนื่องจากภาษามาร์กอัปของฉันมีอักขระเพียงสองหรือสามตัวเท่านั้น ฉันจึงต้องหลีกเลี่ยงวิธีนี้

ฉันจะจับคู่อักขระ Unicode ทั้งหมดกับ python regexs และ ply ได้อย่างไร นี่เป็นความคิดที่ดีหรือไม่?

ฉันต้องการให้ผู้คนใช้ตัวระบุเช่น Ω » « ° foo² väli π เป็นตัวระบุ (ชื่อตัวแปรและอื่น ๆ ) ในโปรแกรมของพวกเขา แฮก! ฉันอยากให้ผู้คนสามารถเขียนโปรแกรมในภาษาของตัวเองได้ถ้ามันใช้งานได้จริง! อย่างไรก็ตาม ทุกวันนี้ Unicode ได้รับการรองรับในหลากหลายตำแหน่ง และควรกระจายออกไป

แก้ไข: ดูเหมือนว่าคลาสอักขระ POSIX จะไม่ได้รับการยอมรับจาก python regexes

>>> import re
>>> item = re.compile(r'[[:word:]]')
>>> print item.match('e')
None

แก้ไข: เพื่ออธิบายสิ่งที่ฉันต้องการได้ดีขึ้น ฉันต้องการ regex ซึ่งตรงกับอักขระ Unicode ที่พิมพ์ได้ทั้งหมด แต่ไม่ใช่อักขระ ASCII เลย

แก้ไข: r"\w" ทำสิ่งที่ฉันต้องการเล็กน้อย แต่มันไม่ตรงกับ « » และฉันก็ต้องการ regex ที่ไม่ตรงกับตัวเลขด้วย


person Cheery    schedule 26.10.2008    source แหล่งที่มา
comment
ยังไม่ปรากฏว่า Python PCRE เข้าใจคลาสเพรดิเคตเช่นกัน: \p{IsAlpha}   -  person Axeman    schedule 27.10.2008


คำตอบ (5)


โมดูล re รองรับไวยากรณ์ \w ซึ่ง:

หากตั้งค่า UNICODE ค่านี้จะจับคู่อักขระ [0-9_] บวกกับอะไรก็ตามที่จัดเป็นตัวอักษรและตัวเลขในฐานข้อมูลคุณสมบัติอักขระ Unicode

ดังนั้นตัวอย่างต่อไปนี้จะแสดงวิธีจับคู่ตัวระบุ Unicode:

>>> import re
>>> m = re.compile('(?u)[^\W0-9]\w*')
>>> m.match('a')
<_sre.SRE_Match object at 0xb7d75410>
>>> m.match('9')
>>> m.match('ab')
<_sre.SRE_Match object at 0xb7c258e0>
>>> m.match('a9')
<_sre.SRE_Match object at 0xb7d75410>
>>> m.match('unicöde')
<_sre.SRE_Match object at 0xb7c258e0>
>>> m.match('ödipus')
<_sre.SRE_Match object at 0xb7d75410>

ดังนั้นนิพจน์ที่คุณค้นหาคือ: (?u)[^\W0-9]\w*

person Florian Bösch    schedule 26.10.2008
comment
ตอนนี้. นี่เป็นทางออกที่น่าพึงพอใจ! - person Cheery; 27.10.2008
comment
คำพูดจากเอกสาร Python นั้นถูกต้อง แต่ตัวอย่างทำให้เข้าใจผิด คุณสามารถใช้แฟล็ก UNICODE ด้วย \w แทนนิพจน์ที่ยาวโดยไม่จำเป็น: re.match(r'\w+', "ünıcodê", re.UNICODE) - person Walter; 27.10.2008
comment
วอลเตอร์ คุณอ่านคำถามไม่ถูกต้อง: 1) เป้าหมายคือตัวระบุในภาษาการเขียนโปรแกรม ซึ่งโดยปกติไม่ได้ขึ้นต้นด้วย 0-9 2) parser (ply) จะดูแลการแยกวิเคราะห์ และไม่สามารถควบคุมได้ว่ามันจะเรียกใช้การจับคู่อย่างไร ดังนั้น (?u) จึงจำเป็น - person Florian Bösch; 27.10.2008
comment
Re: ควบคุมวิธีการเรียกใช้การจับคู่ ดูคำตอบของ Stanislav ด้านล่าง - person Paul Du Bois; 20.12.2011

คุณต้องผ่านการตั้งค่าพารามิเตอร์ pass pass ใน lex.lex:

lex.lex(reflags=re.UNICODE)
person Stan    schedule 14.12.2011

ตรวจสอบคำตอบสำหรับคำถามนี้

การแยกอักขระที่ไม่สามารถพิมพ์ได้ออกจากสตริงใน python

คุณเพียงแค่ต้องใช้หมวดหมู่อักขระ Unicode อื่นแทน

person Vinko Vrsalovic    schedule 26.10.2008

แก้ไขได้ด้วยความช่วยเหลือของ Vinko

ฉันรู้ว่าการรับช่วงยูนิโค้ดนั้นเป็นเรื่องโง่ ดังนั้นฉันจะทำสิ่งนี้:

symbols = re.escape(''.join([chr(i) for i in xrange(33, 127) if not chr(i).isalnum()]))
symnums = re.escape(''.join([chr(i) for i in xrange(33, 127) if not chr(i).isalnum()]))

t_IDENTIFIER = "[^%s](\\.|[^%s])*" % (symnums, symbols)

ฉันไม่รู้เกี่ยวกับคลาสอักขระ Unicode หากยูนิโค้ดนี้เริ่มซับซ้อนเกินไป ฉันก็สามารถใส่อันต้นฉบับเข้าไปที่เดิมได้ การสนับสนุน UTF-8 ยังคงช่วยให้แน่ใจว่าการสนับสนุนเปิดอยู่ที่โทเค็น STRING ซึ่งมีความสำคัญมากกว่า

แก้ไข: ในทางกลับกัน ฉันเริ่มเข้าใจว่าเหตุใดจึงไม่มีการรองรับ Unicode ในภาษาการเขียนโปรแกรมมากนัก .. นี่เป็นแฮ็คที่น่าเกลียด ไม่ใช่วิธีแก้ปัญหาที่น่าพอใจ

person Cheery    schedule 26.10.2008

คลาสอักขระ POSIX อาจเหมาะกับคุณใช่ไหม

person Tomalak    schedule 26.10.2008
comment
ไม่มีอยู่ในเอ็นจิ้น regex ของ Python - person Vinko Vrsalovic; 26.10.2008