32

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?

tchrist
  • 76,727
  • 28
  • 123
  • 176
warvariuc
  • 53,721
  • 35
  • 166
  • 222

1 Answers1

62

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 (if you use the re.UNICODE compile option).

Tim Pietzcker
  • 313,408
  • 56
  • 485
  • 544
  • 2
    I already recognized that `\p{L}` is not supported, so your solution is the way to go +1. – stema Jan 19 '12 at 09:57
  • to include ``-`` in any regex character class, just put it at end (or beginning): ``[^\W\d_-]`` for this example. – RichVel Sep 18 '13 at 15:18
  • 3
    @RichVel: That will *forbid* a minus sign. – Tim Pietzcker Sep 18 '13 at 15:21
  • 2
    @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_]|-)`` – RichVel Sep 19 '13 at 13:16