Matching only a unicode letter in Python re
Asked Answered
S

1

33

I have a string from which i want to extract 3 groups:

'19 janvier 2012' -> '19', 'janvier', '2012'

Month name could contain non ASCII characters, so [A-Za-z] does not work for me:

>>> import re
>>> re.search(ur'(\d{,2}) ([A-Za-z]+) (\d{4})', u'20 janvier 2012', re.UNICODE).groups()
(u'20', u'janvier', u'2012')
>>> re.search(ur'(\d{,2}) ([A-Za-z]+) (\d{4})', u'20 février 2012', re.UNICODE).groups()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'groups'
>>> 

I could use \w but it matches digits and underscore:

>>> re.search(ur'(\w+)', u'février', re.UNICODE).groups()
(u'f\xe9vrier',)
>>> re.search(ur'(\w+)', u'fé_q23vrier', re.UNICODE).groups()
(u'f\xe9_q23vrier',)
>>> 

I tried to use [:alpha:], but it's not working:

>>> re.search(ur'[:alpha:]+', u'février', re.UNICODE).groups()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'groups'
>>> 

If i could somehow match \w without [_0-9], but i don't know how. And even if i find out how to do this, is there a ready shortcut like [:alpha:] which works in Python?

Stilbestrol answered 19/1, 2012 at 9:49 Comment(5)
As for [:alpha:], this only works inside a character class, so the correct regex would be [[:alpha:]]+, but Python doesn't support these anyway.Iredale
Why not simply call .split() on the string?Jeffries
fyi \w already matches unicode see For Unicode (str) patterns: Matches Unicode word characters; this includes most characters that can be part of a word in any language, as well as numbers and the underscore. If the ASCII flag is used, only [a-zA-Z0-9_] is matched. ref docs.python.org/3/library/re.html though idk if we need the re.UNICODE flag.Nasal
do we really need the re.UNICODE flag? The docs seem to imply it already works for unicode: Both patterns and strings to be searched can be Unicode strings (str) as well as 8-bit strings (bytes). correct me if I am wrong. Ref: docs.python.org/3/library/re.htmlNasal
@CharlieParker probably this question was asked during Python 2 era.Stilbestrol
I
64

You can construct a new character class:

[^\W\d_]

instead of \w. Translated into English, it means "Any character that is not a non-alphanumeric character ([^\W] is the same as \w), but that is also not a digit and not an underscore".

Therefore, it will only allow Unicode letters.

Iredale answered 19/1, 2012 at 9:52 Comment(6)
I already recognized that \p{L} is not supported, so your solution is the way to go +1.Quits
to include - in any regex character class, just put it at end (or beginning): [^\W\d_-] for this example.Droplet
@RichVel: That will forbid a minus sign.Iredale
@TimPietzcker - Yes, I didn't read that comment well enough... one solution is to use regex alternation, e.g. something like this (not tested): ([^\W\d_]|-)Droplet
do we really need the re.UNICODE flag? The docs seem to imply it already works for unicode: Both patterns and strings to be searched can be Unicode strings (str) as well as 8-bit strings (bytes). correct me if I am wrong. Ref: docs.python.org/3/library/re.htmlNasal
You're right, in Python 3 it's redundant. 2012, when this answer was written, Python 2 was still dominant, but I guess an edit is in order now :)Iredale

© 2022 - 2024 — McMap. All rights reserved.