Melarikan string regex dengan Python

229

Saya ingin menggunakan input dari pengguna sebagai pola regex untuk pencarian beberapa teks. Ini berfungsi, tetapi bagaimana saya bisa menangani kasus di mana pengguna menempatkan karakter yang memiliki makna di regex? Misalnya, pengguna ingin mencari Word (s): mesin regex akan mengambil (s)sebagai grup. Saya ingin memperlakukannya seperti string "(s)". Saya dapat menjalankan replaceinput pengguna dan mengganti (dengan \(dan )dengan \)tetapi masalahnya adalah saya harus melakukan penggantian untuk setiap simbol regex yang mungkin. Apakah Anda tahu cara yang lebih baik?

MichaelT
sumber

Jawaban:

324

Gunakan re.escape()fungsi untuk ini:

4.2.3 reIsi Modul

melarikan diri (string)

Kembalikan string dengan semua non-alfanumerik backslashed; ini berguna jika Anda ingin mencocokkan string literal sewenang-wenang yang mungkin memiliki metakarakter ekspresi reguler di dalamnya.

Contoh sederhana, cari kemunculan string yang disediakan secara opsional diikuti oleh ',' dan kembalikan objek yang cocok.

def simplistic_plural(word, text):
    word_or_plural = re.escape(word) + 's?'
    return re.match(word_or_plural, text)
ddaa
sumber
53

Anda dapat menggunakan re.escape () :

re.escape (string) Mengembalikan string dengan semua non-alfanumerik yang terbalik; ini berguna jika Anda ingin mencocokkan string literal sewenang-wenang yang mungkin memiliki metakarakter ekspresi reguler di dalamnya.

>>> import re
>>> re.escape('^a.*$')
'\\^a\\.\\*\\$'
Gimel
sumber
3

Sayangnya, re.escape()tidak cocok untuk string pengganti:

>>> re.sub('a', re.escape('_'), 'aa')
'\\_\\_'

Solusinya adalah dengan meletakkan penggantinya dalam lambda:

>>> re.sub('a', lambda _: '_', 'aa')
'__'

karena nilai kembalinya lambda diperlakukan re.sub()sebagai string literal.

Owen
sumber
3
The replargumen untuk re.subadalah string, bukan regex; menerapkannya re.escapetidak masuk akal sejak awal.
tripleee
5
@ tripleee Itu tidak benar, replargumennya bukan string sederhana, itu diuraikan. Misalnya, re.sub(r'(.)', r'\1', 'X')akan kembali X, bukan \1.
Flimm
4
Inilah pertanyaan yang relevan untuk keluar dari replargumen: stackoverflow.com/q/49943270/247696
Flimm
3
Berubah dalam versi 3.3: Karakter '_' tidak lagi lolos. Berubah dalam versi 3.7: Hanya karakter yang dapat memiliki arti khusus dalam ekspresi reguler yang lolos. (Mengapa itu butuh waktu begitu lama?)
Cees Timmerman