Нечувствительное к регистру регулярное выражение без re.compile?


331

В Python я могу скомпилировать регулярное выражение без учета регистра, используя re.compile:

>>> s = 'TeSt'
>>> casesensitive = re.compile('test')
>>> ignorecase = re.compile('test', re.IGNORECASE)
>>> 
>>> print casesensitive.match(s)
None
>>> print ignorecase.match(s)
<_sre.SRE_Match object at 0x02F0B608>

Есть ли способ сделать то же самое, но без использования re.compile. Я не могу найти ничего подобного iсуффиксу Perl (например m/test/i) в документации.


1
Вы можете найти отличное введение в регулярные эксперименты по адресу: python-course.eu/re.php
2Obe

Ответы:


562

Пропустите re.IGNORECASEк flagsпарам из search, matchили sub:

re.search('test', 'TeSt', re.IGNORECASE)
re.match('test', 'TeSt', re.IGNORECASE)
re.sub('test', 'xxxx', 'Testing', flags=re.IGNORECASE)

2
re.match('test', 'TeSt', re.IGNORECASE)может привести к тому, TypeErrorчто любой из атрибутов будет None. Используется try & exceptдля TypeErrorпоиска совпадений по first_string == second_string. Пример кода def equal_ignore_case(first_string, second_string): try: return re.match(first_string, second_string, re.IGNORECASE) is not None except (AttributeError, TypeError): return first_string == second_string Demo Code
Abhijeet

3
@Abhijeet Вы действительно не должны использовать try /, кроме как в этом случае. Просто проверьте, если какие-либо из строк являются Noneпервыми.
Еврорадио

Важно использовать именованный аргумент, flagsпоскольку в re.subпротивном случае он передается re.IGNORECASEв countаргумент (например, stackoverflow.com/questions/42581/… )
L3n95

101

Вы также можете выполнять поиск без учета регистра, используя поиск / совпадение без флага IGNORECASE (протестировано в Python 2.7.3):

re.search(r'(?i)test', 'TeSt').group()    ## returns 'TeSt'
re.match(r'(?i)test', 'TeSt').group()     ## returns 'TeSt'

2
В документации не упоминается функция, добавляемая в какую-либо конкретную версию (в отличие, скажем, от того, (?(condition)yes|no)что говорится в версии 2.4), поэтому я ожидаю, что она всегда была доступна с первой версии reмодуля, которая, я думаю, была добавлена в 1.5. В основном с начала времен для всех намерений и целей, когда дело доходит до Python. Документально описан
ArtOfWarfare

4
Здесь мы идем - я просмотрел документацию для 1.5 и обнаружил, что она документирована примерно на 60% пути вниз по этой странице: docs.python.org/release/1.5/lib/… Я также проверил документацию 1.4, в которой не упоминалось эта особенность. Так что я думаю, что он был добавлен в 1.5, когда regexмодуль устарел в пользу reмодуля.
ArtOfWarfare

3
Это хорошее решение, так как оно не требует флага. В моем случае я храню строки поиска в Redis, и это действительно полезно.
Частное

3
@Private: концептуально он устанавливает флаг re.I для всего регулярного выражения, а не только для группы захвата, которой он предшествует. Имейте в виду, что re.match(r'''A ((?i)B) C''', "a b c").group(0)вызывает сопоставление без учета регистра для всего (A и C), а не только для B! Если вы хотите, чтобы совпадение без учета регистра в определенной группе захвата не выполнялось, это не тот дроид, которого вы ищете.
smci

1
@ ЧАСТНЫЙ: да, полностью. Моя точка зрения концептуально это то же самое, что установить флаг. На все регулярные выражения. Даже группы, которые предшествуют этому (!). Нет синтаксиса, чтобы сказать «нечувствителен к регистру только для следующих групп захвата».
SMCI

53

Маркер (?i)без учета регистра может быть включен непосредственно в шаблон регулярных выражений:

>>> import re
>>> s = 'This is one Test, another TEST, and another test.'
>>> re.findall('(?i)test', s)
['Test', 'TEST', 'test']

2
Лучший вариант, делает регулярное выражение регулярным для всех платформ, и намерение становится ясным при объявлении
Сина Мадани

1
Этот '(?i)'подход также имеет то преимущество, что вы можете создать список регулярных выражений, некоторые из которых не чувствительны к регистру, а некоторые нет. (И, конечно, вы можете отобразить re.compileэтот список, если хотите.)
not-just-

@SinaMadani Я в замешательстве. Как это более портативно, чем flags=re.IGNORECASE?
Ромен Винсент

10

Вы также можете определить регистр без учета регистра во время компиляции шаблона:

pattern = re.compile('FIle:/+(.*)', re.IGNORECASE)

5
В вопросе OP использует это и спрашивает, есть ли другой способ сделать это.
Питер Вуд

6
Полезно для быстрых прокруток.
Stevek

6

В импорте

import re

Во время выполнения обработки:

RE_TEST = r'test'
if re.match(RE_TEST, 'TeSt', re.IGNORECASE):

Следует отметить, что неиспользование re.compileявляется расточительным. Каждый раз, когда вызывается вышеуказанный метод match, регулярное выражение будет компилироваться. Это также ошибочная практика на других языках программирования. Ниже приведена лучшая практика.

При инициализации приложения:

self.RE_TEST = re.compile('test', re.IGNORECASE)

Во время выполнения обработки:

if self.RE_TEST.match('TeSt'):

1
Спасибо! Никто никогда не говорит о компиляции, но это самый умный вариант!
StefanJCollier

2
ОП буквально просит решение, которое не использует re.compile()....
wpercy

4
#'re.IGNORECASE' for case insensitive results short form re.I
#'re.match' returns the first match located from the start of the string. 
#'re.search' returns location of the where the match is found 
#'re.compile' creates a regex object that can be used for multiple matches

 >>> s = r'TeSt'   
 >>> print (re.match(s, r'test123', re.I))
 <_sre.SRE_Match object; span=(0, 4), match='test'>
 # OR
 >>> pattern = re.compile(s, re.I)
 >>> print(pattern.match(r'test123'))
 <_sre.SRE_Match object; span=(0, 4), match='test'>

4

Для выполнения операций без учета регистра поставьте re.IGNORECASE

>>> import re
>>> test = 'UPPER TEXT, lower text, Mixed Text'
>>> re.findall('text', test, flags=re.IGNORECASE)
['TEXT', 'text', 'Text']

и если мы хотим заменить текст, соответствующий регистру ...

>>> def matchcase(word):
        def replace(m):
            text = m.group()
            if text.isupper():
                return word.upper()
            elif text.islower():
                return word.lower()
            elif text[0].isupper():
                return word.capitalize()
            else:
                return word
        return replace

>>> re.sub('text', matchcase('word'), test, flags=re.IGNORECASE)
'UPPER WORD, lower word, Mixed Word'

1

Если вы хотите заменить, но сохраняя стиль предыдущей ул. Это возможно.

Например: выделите строку «test asdasd TEST asd tEst asdasd».

sentence = "test asdasd TEST asd tEst asdasd"
result = re.sub(
  '(test)', 
  r'<b>\1</b>',  # \1 here indicates first matching group.
  sentence, 
  flags=re.IGNORECASE)

Тест Asdasd TEST ASD TEST Asdasd


0

Для регистрозависимого регулярного выражения (Regex): есть два способа добавления в ваш код:

  1. flags=re.IGNORECASE

    Regx3GList = re.search("(WCDMA:)((\d*)(,?))*", txt, **re.IGNORECASE**)
  2. Нечувствительный к регистру маркер (?i)

    Regx3GList = re.search("**(?i)**(WCDMA:)((\d*)(,?))*", txt)
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.