Kasus ekspresi reguler tidak peka tanpa kompilasi ulang?


331

Dengan Python, saya bisa mengkompilasi ekspresi reguler menjadi case-insensitive menggunakan 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>

Apakah ada cara untuk melakukan hal yang sama, tetapi tanpa menggunakan re.compile. Saya tidak dapat menemukan isufiks seperti Perl (misalnya m/test/i) dalam dokumentasi.


1
Anda dapat menemukan pengantar yang bagus untuk experssoins reguler di: python-course.eu/re.php
2Obe

Jawaban:


562

Lulus re.IGNORECASEdengan flagsparam dari search, matchatau 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)mungkin mengarah ke TypeErrorsaat salah satu atribut sedang None. Menggunakan try & exceptuntuk menangkap TypeErrorpencocokan dengan first_string == second_string. Contoh Kode Kode 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
Abhijeet

3
@Abhijeet Anda sebaiknya tidak menggunakan coba / kecuali dalam hal itu. Periksa apakah ada dawai yang Nonepertama.
erb

Sangat penting untuk menggunakan argumen yang disebutkan flagskarena re.subjika tidak, argumen tersebut akan diteruskan re.IGNORECASEke countargumen (s. Juga stackoverflow.com/questions/42581/… )
L3n95

101

Anda juga dapat melakukan pencarian yang tidak peka terhadap huruf besar-kecil menggunakan pencarian / kecocokan tanpa flag IGNORECASE (diuji dengan Python 2.7.3):

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

2
Dokumentasi tidak menyebutkan fitur yang ditambahkan dalam versi tertentu (sebagai kebalikan dari, katakan (?(condition)yes|no)yang katanya ditambahkan dalam 2.4), jadi saya berharap itu selalu tersedia sejak versi pertama remodul, yang saya pikir telah ditambahkan dalam 1.5. Pada dasarnya sejak awal waktu untuk semua maksud dan tujuan ketika datang ke Python. Ini didokumentasikan sekitar setengah jalan melalui bagian pertama dari halaman ini: docs.python.org/2/library/re.html#regular-expression-syntax
ArtOfWarfare

4
Di sini kita pergi - saya melihat melalui dokumentasi untuk 1,5 dan menemukan itu mendokumentasikan sekitar 60% dari jalan ke bawah halaman ini: docs.python.org/release/1.5/lib/... Saya juga memeriksa dokumentasi 1.4, yang tidak menyebutkan tentang fitur ini. Jadi saya kira itu ditambahkan dalam 1,5, ketika regexmodul itu ditinggalkan demi remodul.
ArtOfWarfare

3
Ini adalah solusi yang bagus karena tidak memerlukan bendera. Dalam kasus saya, saya menyimpan string pencarian di Redis dan ini sangat membantu.
Pribadi

3
@Private: secara konseptual ia mengatur bendera re.I di seluruh regex - bukan hanya grup tangkapan yang didahului. Perlu diketahui bahwa re.match(r'''A ((?i)B) C''', "a b c").group(0)menyebabkan pencocokan case-insensitive pada segalanya (A dan C), tidak hanya pada B! Jika Anda hanya menginginkan insen yang sesuai dengan kelompok tangkapan tertentu, ini bukan droid yang Anda cari.
smci

1
@Private: ya benar. Maksud saya secara konseptual itu sama dengan mengatur bendera. Di seluruh regex. Bahkan kelompok yang mendahuluinya (!). Tidak ada sintaks yang mengatakan "case-insensitive hanya pada kelompok tangkapan berikut".
smci

53

Penanda case-insensitive, (?i)dapat dimasukkan langsung ke dalam pola regex:

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

2
Opsi yang lebih baik, menjadikan regex portable di seluruh platform dan niat jelas saat deklarasi
Sina Madani

1
'(?i)'Pendekatan ini juga memiliki keuntungan bahwa Anda dapat membuat daftar regexp, beberapa di antaranya tidak peka huruf besar kecil dan beberapa tidak. (Dan tentu saja, Anda dapat memetakan re.compiledaftar itu jika Anda mau.)
not-just-yeti

@SinaMadani saya bingung. Bagaimana itu lebih portabel daripada flags=re.IGNORECASE?
Romain Vincent

10

Anda juga dapat mendefinisikan huruf besar-kecil selama kompilasi pola:

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

5
Dalam pertanyaan, OP menggunakan ini dan menanyakan apakah ada cara lain untuk melakukannya.
Peter Wood

6
Bermanfaat untuk yang gulir cepat.
stevek

6

Di impor

import re

Dalam pemrosesan waktu berjalan:

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

Harus disebutkan bahwa tidak menggunakan re.compileitu boros. Setiap kali metode pencocokan di atas dipanggil, ekspresi reguler akan dikompilasi. Ini juga praktik yang salah dalam bahasa pemrograman lain. Di bawah ini adalah praktik yang lebih baik.

Dalam inisialisasi aplikasi:

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

Dalam pemrosesan waktu berjalan:

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

1
Terima kasih! Tidak ada yang pernah berbicara tentang kompilasi, namun itu adalah pilihan paling cerdas!
StefanJCollier

2
OP benar-benar meminta solusi yang tidak menggunakan 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

Untuk melakukan operasi case-insensitive, berikan re.IGNORECASE

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

dan jika kami ingin mengganti teks yang cocok dengan case ...

>>> 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

Jika Anda ingin mengganti tetapi tetap mempertahankan gaya str sebelumnya. Itu mungkin.

Sebagai contoh: sorot string "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


0

Untuk ekspresi reguler yang tidak sensitif huruf (Regex): Ada dua cara dengan menambahkan kode Anda:

  1. flags=re.IGNORECASE

    Regx3GList = re.search("(WCDMA:)((\d*)(,?))*", txt, **re.IGNORECASE**)
  2. Penanda case-insensitive (?i)

    Regx3GList = re.search("**(?i)**(WCDMA:)((\d*)(,?))*", txt)
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.