ignore case only for a part of the regex?

Vlastimil Brom vlastimil.brom at gmail.com
Wed Jan 2 00:09:45 CET 2013


2013/1/1 Steven D'Aprano <steve+comp.lang.python at pearwood.info>:
> On Sun, 30 Dec 2012 10:20:19 -0500, Roy Smith wrote:
>
>> The way I would typically do something like this is build my regexes in
>> all lower case and .lower() the text I was matching against them.  I'm
>> curious what you're doing where you want to enforce case sensitivity in
>> one part of a header, but not in another.
>
> Well, sometimes you have things that are case sensitive, and other things
> which are not, and sometimes you need to match them at the same time. I
> don't think this is any more unusual than (say) wanting to match an
> otherwise lowercase word whether or not it comes at the start of a
> sentence:
>
> "[Pp]rogramming"
>
> is conceptually equivalent to "match case-insensitive `p`, and case-
> sensitive `rogramming`".
>
>
> By the way, although there is probably nothing you can (easily) do about
> this prior to Python 3.3, converting to lowercase is not the right way to
> do case-insensitive matching. It happens to work correctly for ASCII, but
> it is not correct for all alphabetic characters.
>
>
> py> 'Straße'.lower()
> 'straße'
> py> 'Straße'.upper()
> 'STRASSE'
>
>
> The right way is to casefold first, then match:
>
> py> 'Straße'.casefold()
> 'strasse'
>
>
> Curiously, there is an uppercase ß in old German. In recent years some
> typographers have started using it instead of SS, but it's still rare,
> and the official German rules have ß transform into SS and vice versa.
> It's in Unicode, but few fonts show it:
>
> py> unicodedata.lookup('LATIN CAPITAL LETTER SHARP S')
> 'ẞ'
>
>
>
> --
> Steven
> --
> http://mail.python.org/mailman/listinfo/python-list

Hi,
just for completeness, the mentioned regex library can take care of
casfolding in case insensitive matching (in all supported versions:
Python 2.5-2.7 and 3.1-3.3); i.e.:
# case sensitive match:
>>> for m in regex.findall(ur"Straße", u" STRAßE STRASSE STRAẞE Strasse Straße "): print m
...
Straße

# case insensitive match:
>>> for m in regex.findall(ur"(?i)Straße", u" STRAßE STRASSE STRAẞE Strasse Straße "): print m
...
STRAßE
STRAẞE
Straße

# case insensitive match with casefolding:
>>> for m in regex.findall(ur"(?if)Straße", u" STRAßE STRASSE STRAẞE Strasse Straße "): print m
...
STRAßE
STRASSE
STRAẞE
Strasse
Straße
>>>
>>>

# after enabling the backwards incompatible modern matching behaviour,
casefolding is by default turned on for case insensitive matches
>>> for m in regex.findall(ur"(?V1i)Straße", u" STRAßE STRASSE STRAẞE Strasse Straße "): print m
...
STRAßE
STRASSE
STRAẞE
Strasse
Straße
>>>


As a small addition, the originally posted pattern r'^Msg-(?:(?i)id):'
would actually work as expected in this modern matching mode in regex
- enabled with the V1 flag. In this case the flag-setting (?i) only
affects the following parts of the pattern, not the whole pattern like
in the current "re" and V0-compatibility-mode "regex"

>>> regex.findall(r"(?V1)Msg-(?:(?i)id):", "the regex should match  Msg-id:, Msg-Id:, ...  but not  msg-id:, MSG-ID:  and so on")
['Msg-id:', 'Msg-Id:']
>>>

regards,
      vbr



More information about the Python-list mailing list