Wyrażenie regularne bez rozróżniania wielkości liter bez ponownej kompilacji?

331

W Pythonie mogę skompilować wyrażenie regularne bez rozróżniania wielkości liter, używając 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>

Czy istnieje sposób na zrobienie tego samego, ale bez użycia re.compile. Nie mogę znaleźć czegoś takiego jak iprzyrostek Perla (np. m/test/i) W dokumentacji.

Mata
źródło
1
Doskonałe wprowadzenie do regularnych experssoin można znaleźć na stronie: python-course.eu/re.php
2

Odpowiedzi:

562

Przechodzą re.IGNORECASEdo flagsparam z search, matchlub sub:

re.search('test', 'TeSt', re.IGNORECASE)
re.match('test', 'TeSt', re.IGNORECASE)
re.sub('test', 'xxxx', 'Testing', flags=re.IGNORECASE)
Michael Haren
źródło
2
re.match('test', 'TeSt', re.IGNORECASE)może prowadzić do tego, TypeErrorże którykolwiek z atrybutów jest None. Używanie try & exceptdo łapania TypeErrordopasowania przez first_string == second_string. Przykładowy kod 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 Naprawdę nie powinieneś używać try / oprócz tego przypadku. Po prostu sprawdź, czy któryś z ciągów jest Nonepierwszy.
erb
Ważne jest, aby użyć nazwanego argumentu, flagsponieważ w re.subprzeciwnym razie zostanie on przekazany re.IGNORECASEdo countargumentu (
patrz
101

Możesz także wyszukiwać bez rozróżniania wielkości liter, używając wyszukiwania / dopasowania bez flagi IGNORECASE (testowane w Pythonie 2.7.3):

re.search(r'(?i)test', 'TeSt').group()    ## returns 'TeSt'
re.match(r'(?i)test', 'TeSt').group()     ## returns 'TeSt'
aem999
źródło
2
Dokumentacja nie wspomina o funkcji dodawanej w żadnej konkretnej wersji (w przeciwieństwie do, powiedzmy (?(condition)yes|no), że jest dodana w 2.4), więc spodziewam się, że zawsze była dostępna od pierwszej wersji remodułu, która, jak myślę, została dodana w 1.5. Zasadniczo od początku czasu dla wszystkich celów i celów, jeśli chodzi o Python. Jest udokumentowany mniej więcej w połowie pierwszej części tej strony: docs.python.org/2/library/re.html#regular-expression-syntax
ArtOfWarfare
4
Proszę bardzo - przejrzałem dokumentację 1.5 i znalazłem ją udokumentowaną w około 60% w dół tej strony: docs.python.org/release/1.5/lib/ ... Sprawdziłem również dokumentację 1.4, w której nie wspomniałem o ta cecha. Sądzę więc, że został dodany w wersji 1.5, gdy regexmoduł został wycofany na korzyść remodułu.
ArtOfWarfare
3
To dobre rozwiązanie, ponieważ nie wymaga flagi. W moim przypadku przechowuję ciągi wyszukiwania w Redis i to jest naprawdę pomocne.
Prywatny
3
@Private: koncepcyjnie ustawia flagę re.I na całym wyrażeniu regularnym - nie tylko na grupie przechwytywania, którą poprzedza. Pamiętaj, że re.match(r'''A ((?i)B) C''', "a b c").group(0)powoduje to rozróżnianie wielkości liter we wszystkich elementach (A i C), nie tylko w B! Jeśli chcesz dopasowywać rozróżnianie wielkości liter tylko do określonej grupy przechwytywania, nie jest to droid, którego szukasz.
smci,
1
@Prywatne: tak całkowicie. Chodzi mi o to, że jest to tak samo jak ustawienie flagi. Na całym wyrażeniu regularnym. Nawet grupy, które go poprzedzają (!). Nie ma składni, by powiedzieć „bez rozróżniania wielkości liter tylko w następujących grupach przechwytywania”.
smci,
53

Znacznik bez rozróżniania wielkości liter (?i)może zostać włączony bezpośrednio do wzoru wyrażenia regularnego:

>>> import re
>>> s = 'This is one Test, another TEST, and another test.'
>>> re.findall('(?i)test', s)
['Test', 'TEST', 'test']
Raymond Hettinger
źródło
2
Lepsza opcja, sprawia, że ​​regex jest przenośny na różnych platformach, a deklaracja jest jasna
Sina Madani
1
To '(?i)'podejście ma również tę zaletę, że można utworzyć listę wyrażeń regularnych, z których niektóre są wielkości liter, a niektóre nie. (I oczywiście, jeśli chcesz, możesz zmapować re.compiletę listę).
not-just-yeti
@SinaMadani Jestem zdezorientowany. Jak to jest bardziej przenośne niż flags=re.IGNORECASE?
Romain Vincent
10

Podczas kompilacji wzorca możesz także zdefiniować wielkość liter bez rozróżniania wielkości liter:

pattern = re.compile('FIle:/+(.*)', re.IGNORECASE)
panofish
źródło
5
W pytaniu OP używa tego i pyta, czy jest inny sposób, aby to zrobić.
Peter Wood
6
Pomocne dla szybko przewijających się.
stevek
6

W imporcie

import re

Przetwarzanie w czasie wykonywania:

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

Należy wspomnieć, że nieużywanie re.compilejest marnotrawstwem. Za każdym razem, gdy wywoływana jest powyższa metoda dopasowania, wyrażenie regularne będzie kompilowane. Jest to również błędna praktyka w innych językach programowania. Poniżej znajduje się lepsza praktyka.

Podczas inicjalizacji aplikacji:

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

Przetwarzanie w czasie wykonywania:

if self.RE_TEST.match('TeSt'):
Douglas Daseeco
źródło
1
Dziękuję Ci! Nikt nigdy nie mówi o kompilacji, ale jest to najmądrzejsza opcja!
StefanJCollier
2
OP dosłownie prosi o rozwiązanie, które nie wykorzystuje 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'>
jackotonye
źródło
4

Aby wykonać operacje bez rozróżniania wielkości liter, podaj polecenie RE.IGNORECASE

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

a jeśli chcemy zastąpić tekst pasujący do sprawy ...

>>> 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'
Srivastava
źródło
1

Jeśli chcesz zastąpić, ale nadal zachować styl poprzedniego str. To jest możliwe.

Na przykład: zaznacz ciąg „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)

test asdasd TEST asd tEst asdasd

Dat Nguyen
źródło
0

W przypadku wyrażeń regularnych bez rozróżniania wielkości liter (Regex): Istnieją dwa sposoby dodania kodu:

  1. flags=re.IGNORECASE

    Regx3GList = re.search("(WCDMA:)((\d*)(,?))*", txt, **re.IGNORECASE**)
  2. Znacznik bez rozróżniania wielkości liter (?i)

    Regx3GList = re.search("**(?i)**(WCDMA:)((\d*)(,?))*", txt)
Aliakbar Hosseinzadeh
źródło