Випадкові безчутливі регулярні вирази без 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суфікс Перла (наприклад 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 демо-коду
Abhijeet

3
@Abhijeet Ви дійсно не повинні використовувати try / за винятком цього випадку. Просто перевірте, чи є будь-який з рядків Noneпершим.
erb

Важливо використовувати іменований аргумент 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. Це задокументовано приблизно на півдорозі через перший розділ цієї сторінки: docs.python.org/2/library/re.html#regular-expression-syntax
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
Кращий варіант, робить регекс переносним на будь-яких платформах, а наміри зрозумілі при декларації
Sina Madani

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

@SinaMadani Я розгублений. Як це більш портативно, ніж flags=re.IGNORECASE?
Ромен Вінсент

10

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

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

5
У питанні ОП використовує це і запитує, чи є інший спосіб зробити це.
Пітер Вуд

6
Корисно для швидко прокручуваних.
stevek

6

В імпорті

import re

Під час обробки часу:

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

Слід зазначити, що не використовувати re.compileмарно. Кожен раз, коли виклик вищезгаданого методу відповідності, буде складено регулярний вираз. Це також є несправною практикою в інших мовах програмування. Нижче - краща практика.

У ініціалізації програми:

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

Під час обробки часу:

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

1
Дякую! Ніхто ніколи не говорить про компіляцію, але це найрозумніший варіант!
StefanJCollier

2
OP буквально просить рішення , яке НЕ використовують 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

Щоб виконати нечутливі до регістру операції, поставте ре.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

Якщо ви хочете замінити, але все-таки зберегти стиль попередньої str. Можливо.

Наприклад: виділіть рядок "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.