Подтвердить что ты не робот

Почему флаг ignorecase (re.I) не работает в re.sub()

Из pydoc:

re.sub = sub (pattern, repl, string, count = 0, flags = 0)
    Вернуть строку, полученную путем замены самого левого     неперекрывающиеся вхождения шаблона в строке с помощью     замена. repl может быть либо строкой, либо вызываемой;     если строка, обратная косая черта в ней обрабатывается. Если это     вызываемый, он передает объект соответствия и должен возвращаться     заменяющую строку, которая будет использоваться.

пример кода:

import re
print re.sub('class', 'function', 'Class object', re.I)

Никакая замена не производится, если я не изменю шаблон на "Класс".

Документация не упоминает ничего об этом ограничении, поэтому я предполагаю, что я могу делать что-то неправильно.

Что здесь происходит?

4b9b3361

Ответ 1

Мне кажется, что вы должны делать:

import re
print re.sub('class', 'function', 'Class object', flags=re.I)

Без этого аргумент re.I передается аргументу count.

Ответ 2

Аргумент flags является пятым - вы передаете значение re.I в качестве аргумента count (легко сделать ошибку).

Ответ 3

Примечание для тех, кто по-прежнему занимается установкой Python 2.6.x или старше. Документация Python для 2.6 re говорит:

re.sub(pattern, repl, string[, count])

re.compile(pattern[, flags])

Это означает, что вы не можете передавать флаги непосредственно в sub. Их можно использовать только с компиляцией:

regex = re.compile('class', re.I)
regex.sub("function", "Class object")

Ответ 4

Чтобы избежать ошибок такого типа, можно использовать следующие исправления для обезьян:

import re
re.sub = lambda pattern, repl, string, *, count=0, flags=0, _fun=re.sub: \
    _fun(pattern, repl, string, count=count, flags=flags)

(* запретить указание count, flags в качестве позиционных аргументов. _fun=re.sub - использовать время объявления re.sub.)

Демо:

$ python
Python 3.4.2 (default, Oct  8 2014, 10:45:20) 
[GCC 4.9.1] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import re
>>> re.sub(r'\b or \b', ',', 'or x', re.X)
'or x'   # ?!
>>> re.sub = lambda pattern, repl, string, *, count=0, flags=0, _fun=re.sub: \
...     _fun(pattern, repl, string, count=count, flags=flags)
>>> re.sub(r'\b or \b', ',', 'or x', re.X)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: <lambda>() takes 3 positional arguments but 4 were given
>>> re.sub(r'\b or \b', ',', 'or x', flags=re.X)
', x'
>>> 

Ответ 5

Просто чтобы добавить в Сеппо ответ. Согласно http://docs.python.org/2.6/library/re.html, все еще есть способ передавать флаги непосредственно в 'sub' в 2.6, что может быть полезно, если вам нужно сделать код 2.7 с большим количеством суб-совместимых с 2.6. Цитировать руководство:

... если вам нужно указать флаги регулярного выражения, вы должны использовать объект RE или использовать встроенные модификаторы в шаблоне; например, sub ("(? i) b+", "x", "bbbb BBBB") возвращает 'x x'

и

(? iLmsux) (Одна или несколько букв из набора 'i', 'L', 'm', 's', 'u', 'x'.) Группа соответствует пустой строке; буквы устанавливают соответствующие флаги: re.I (игнорировать регистр), re.L (зависит от локали), re.M (многострочный), re.S (точка соответствует всем), re.U (зависит от Unicode) и re.X (многословный), для всего регулярного выражения. (Флаги описаны в Содержании модуля.) Это полезно, если вы хотите включить флаги как часть регулярного выражения вместо передачи аргумента флага в функцию re.compile().

На практике это означает, что

print re.sub("class", "function", "Class object", flags=re.I)

может быть переписан с использованием модификаторов (? мс) как

print re.sub("(?i)class", "function", "Class object")