Cara menggunakan modul ungkapan biasa Python semula (padanan, carian, sub, dll.)

Perniagaan

Untuk melaksanakan pemprosesan ungkapan biasa dalam Python, kami menggunakan modul semula daripada perpustakaan standard. Ia membolehkan anda mengekstrak, menggantikan dan memisahkan rentetan menggunakan corak ungkapan biasa.

Dalam bahagian ini, kami akan menerangkan terlebih dahulu fungsi dan kaedah modul semula.

  • Menyusun corak ungkapan biasa:compile()
  • objek padan
  • Semak sama ada permulaan rentetan sepadan, ekstrak:match()
  • Semak perlawanan tidak terhad pada permulaan:search()
  • Semak sama ada keseluruhan rentetan sepadan:fullmatch()
  • Dapatkan senarai semua bahagian yang sepadan:findall()
  • Dapatkan semua bahagian yang sepadan sebagai iterator:finditer()
  • Gantikan bahagian yang sepadan:sub(),subn()
  • Memisahkan rentetan dengan corak ungkapan biasa:split()

Selepas itu, saya akan menerangkan aksara meta (watak khas) dan urutan khas ungkapan biasa yang boleh digunakan dalam modul semula. Pada asasnya, ia adalah sintaks ungkapan biasa standard, tetapi berhati-hati tentang menetapkan bendera (terutamanya re.ASCII).

  • Metakarakter ungkapan biasa, jujukan khas dan kaveat dalam Python
  • Menetapkan bendera
    • Terhad kepada aksara ASCII:re.ASCII
    • Tidak sensitif huruf besar-besaran:re.IGNORECASE
    • Padankan permulaan dan penghujung setiap baris:re.MULTILINE
    • Tentukan berbilang bendera
  • Perlawanan tamak dan tidak tamak

Susun corak ungkapan biasa: compile()

Terdapat dua cara untuk melaksanakan pemprosesan ungkapan biasa dalam modul semula.

Jalankan dengan fungsi

Yang pertama ialah fungsi.re.match(),re.sub()Fungsi seperti ini tersedia untuk melaksanakan pengekstrakan, penggantian dan proses lain menggunakan corak ungkapan biasa.

Butiran fungsi akan diterangkan kemudian, tetapi dalam kesemuanya, hujah pertama ialah rentetan corak ungkapan biasa, diikuti dengan rentetan yang akan diproses dan seterusnya. Contohnya, dalam re.sub(), yang melakukan penggantian, argumen kedua ialah rentetan penggantian dan argumen ketiga ialah rentetan yang akan diproses.

import re

s = 'aaa@xxx.com, bbb@yyy.com, ccc@zzz.net'

m = re.match(r'([a-z]+)@([a-z]+)\.com', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>

result = re.sub(r'([a-z]+)@([a-z]+)\.com', 'new-address', s)
print(result)
# new-address, new-address, ccc@zzz.net

Ambil perhatian bahawa [a-z] dalam corak ungkapan biasa dalam contoh ini bermaksud sebarang aksara dari a hingga z (iaitu abjad huruf kecil), dan + bermaksud ulangi corak sebelumnya (dalam kes ini [a-z]) satu kali atau lebih. [a-z]+ sepadan dengan mana-mana rentetan yang mengulangi satu atau lebih aksara abjad huruf kecil.

. ialah watak meta (watak dengan makna istimewa) dan mesti dilepaskan dengan garis serong ke belakang.

Memandangkan rentetan corak ungkapan biasa sering menggunakan banyak garis miring ke belakang, adalah mudah untuk menggunakan rentetan mentah seperti dalam contoh.

Berjalan dalam kaedah objek corak ungkapan biasa

Cara kedua untuk memproses ungkapan biasa dalam modul semula ialah kaedah objek corak ungkapan biasa.

Menggunakan re.compile(), anda boleh menyusun rentetan corak ungkapan biasa untuk mencipta objek corak ungkapan biasa.

p = re.compile(r'([a-z]+)@([a-z]+)\.com')

print(p)
# re.compile('([a-z]+)@([a-z]+)\\.com')

print(type(p))
# <class 're.Pattern'>

re.match(),re.sub()Sebagai contoh, proses yang sama seperti fungsi ini boleh dilaksanakan sebagai kaedah padanan(),sub() bagi objek ungkapan biasa.

m = p.match(s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>

result = p.sub('new-address', s)
print(result)
# new-address, new-address, ccc@zzz.net

Semua fungsi re.xxx() yang diterangkan di bawah juga disediakan sebagai kaedah objek ungkapan biasa.

Jika anda mengulangi proses yang menggunakan corak yang sama, adalah lebih cekap untuk menjana objek ungkapan biasa dengan re.compile() dan menggunakannya di sekeliling.

Dalam kod sampel berikut, fungsi digunakan tanpa menyusun untuk kemudahan, tetapi jika anda ingin menggunakan corak yang sama berulang kali, adalah disyorkan untuk menyusunnya terlebih dahulu dan melaksanakannya sebagai kaedah objek ungkapan biasa.

objek padan

padanan(), carian(), dsb. kembalikan objek padanan.

s = 'aaa@xxx.com'

m = re.match(r'[a-z]+@[a-z]+\.[a-z]+', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>

print(type(m))
# <class 're.Match'>

Rentetan dan kedudukan yang dipadankan diperoleh menggunakan kaedah objek padanan berikut.

  • Dapatkan lokasi perlawanan:start(),end(),span()
  • Dapatkan rentetan yang dipadankan:group()
  • Dapatkan rentetan untuk setiap kumpulan:groups()
print(m.start())
# 0

print(m.end())
# 11

print(m.span())
# (0, 11)

print(m.group())
# aaa@xxx.com

Jika anda melampirkan sebahagian daripada corak ungkapan biasa dalam rentetan dengan kurungan(), bahagian itu akan diproses sebagai satu kumpulan. Dalam kes ini, rentetan bahagian yang sepadan dengan setiap kumpulan dalam kumpulan() boleh diperolehi sebagai tupel.

m = re.match(r'([a-z]+)@([a-z]+)\.([a-z]+)', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>

print(m.groups())
# ('aaa', 'xxx', 'com')

Semak sama ada permulaan rentetan sepadan, ekstrak: match()

match() mengembalikan objek padanan jika permulaan rentetan sepadan dengan corak.

Seperti yang dinyatakan di atas, objek padanan boleh digunakan untuk mengekstrak subrentetan yang dipadankan, atau hanya untuk menyemak sama ada padanan telah dibuat.

match() hanya akan menyemak permulaan. Jika tiada rentetan yang sepadan pada permulaan, ia mengembalikan Tiada.

s = 'aaa@xxx.com, bbb@yyy.com, ccc@zzz.net'

m = re.match(r'[a-z]+@[a-z]+\.com', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>

m = re.match(r'[a-z]+@[a-z]+\.net', s)
print(m)
# None

Semak padanan tidak terhad pada permulaan, ekstrak: search()

Seperti padanan(), ia mengembalikan objek padanan jika ia sepadan.

Jika terdapat beberapa bahagian yang sepadan, hanya bahagian yang sepadan yang pertama akan dikembalikan.

s = 'aaa@xxx.com, bbb@yyy.com, ccc@zzz.net'

m = re.search(r'[a-z]+@[a-z]+\.net', s)
print(m)
# <re.Match object; span=(26, 37), match='ccc@zzz.net'>

m = re.search(r'[a-z]+@[a-z]+\.com', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>

Jika anda ingin mendapatkan semua bahagian yang sepadan, gunakan findall() atau finditer() seperti yang diterangkan di bawah.

Semak sama ada keseluruhan rentetan sepadan: fullmatch()

Untuk menyemak sama ada keseluruhan rentetan sepadan dengan corak ungkapan biasa, gunakan fullmatch(). Ini berguna, sebagai contoh, untuk menyemak sama ada rentetan sah sebagai alamat e-mel atau tidak.

Jika keseluruhan rentetan sepadan, objek padanan dikembalikan.

s = 'aaa@xxx.com'

m = re.fullmatch(r'[a-z]+@[a-z]+\.com', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>

Jika terdapat bahagian yang tidak sepadan (hanya padanan separa atau tiada padanan langsung), Tiada akan dikembalikan.

s = '!!!aaa@xxx.com!!!'

m = re.fullmatch(r'[a-z]+@[a-z]+\.com', s)
print(m)
# None

Fullmatch() telah ditambahkan dalam Python 3.4. Jika anda ingin melakukan perkara yang sama dalam versi terdahulu, gunakan match() dan aksara meta yang sepadan $ pada penghujungnya. Jika keseluruhan rentetan dari awal hingga akhir tidak sepadan, ia mengembalikan Tiada.

s = '!!!aaa@xxx.com!!!'

m = re.match(r'[a-z]+@[a-z]+\.com$', s)
print(m)
# None

Dapatkan senarai semua bahagian yang sepadan: findall()

findall() mengembalikan senarai semua subrentetan yang sepadan. Ambil perhatian bahawa elemen senarai bukan objek padanan tetapi rentetan.

s = 'aaa@xxx.com, bbb@yyy.com, ccc@zzz.net'

result = re.findall(r'[a-z]+@[a-z]+\.[a-z]+', s)
print(result)
# ['aaa@xxx.com', 'bbb@yyy.com', 'ccc@zzz.net']

Bilangan bahagian yang dipadankan boleh disemak menggunakan fungsi terbina dalam len(), yang mengembalikan bilangan elemen dalam senarai.

print(len(result))
# 3

Pengumpulan dengan kurungan() dalam corak ungkapan biasa mengembalikan senarai tupel yang unsur-unsurnya ialah rentetan bagi setiap kumpulan. Ini bersamaan dengan kumpulan() dalam objek padanan.

result = re.findall(r'([a-z]+)@([a-z]+)\.([a-z]+)', s)
print(result)
# [('aaa', 'xxx', 'com'), ('bbb', 'yyy', 'com'), ('ccc', 'zzz', 'net')]

Tanda kurung kumpulan () boleh bersarang, jadi jika anda ingin mendapatkan keseluruhan padanan juga, hanya sertakan keseluruhan padanan dalam kurungan ().

result = re.findall(r'(([a-z]+)@([a-z]+)\.([a-z]+))', s)
print(result)
# [('aaa@xxx.com', 'aaa', 'xxx', 'com'), ('bbb@yyy.com', 'bbb', 'yyy', 'com'), ('ccc@zzz.net', 'ccc', 'zzz', 'net')]

Jika tiada padanan ditemui, tuple kosong dikembalikan.

result = re.findall('[0-9]+', s)
print(result)
# []

Dapatkan semua bahagian yang sepadan sebagai iterator: finditer()

finditer() mengembalikan semua bahagian yang sepadan sebagai iterator. Unsur-unsur itu bukan rentetan seperti findall(), tetapi padankan objek, jadi anda boleh mendapatkan kedudukan (indeks) bahagian yang dipadankan.

Iterator itu sendiri tidak boleh dicetak dengan print() untuk mendapatkan kandungannya. Jika anda menggunakan fungsi terbina dalam next() atau pernyataan for, anda boleh mendapatkan kandungannya satu demi satu.

s = 'aaa@xxx.com, bbb@yyy.com, ccc@zzz.net'

result = re.finditer(r'[a-z]+@[a-z]+\.[a-z]+', s)
print(result)
# <callable_iterator object at 0x10b0efa90>

print(type(result))
# <class 'callable_iterator'>

for m in result:
    print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>
# <re.Match object; span=(13, 24), match='bbb@yyy.com'>
# <re.Match object; span=(26, 37), match='ccc@zzz.net'>

Ia juga boleh ditukar kepada senarai dengan list().

l = list(re.finditer(r'[a-z]+@[a-z]+\.[a-z]+', s))
print(l)
# [<re.Match object; span=(0, 11), match='aaa@xxx.com'>, <re.Match object; span=(13, 24), match='bbb@yyy.com'>, <re.Match object; span=(26, 37), match='ccc@zzz.net'>]

print(l[0])
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>

print(type(l[0]))
# <class 're.Match'>

print(l[0].span())
# (0, 11)

Jika anda ingin mendapatkan kedudukan semua bahagian yang sepadan, tatatanda pemahaman senarai adalah lebih mudah daripada senarai().

print([m.span() for m in re.finditer(r'[a-z]+@[a-z]+\.[a-z]+', s)])
# [(0, 11), (13, 24), (26, 37)]

Iterator mengeluarkan elemen mengikut tertib. Ambil perhatian bahawa jika anda cuba mengekstrak lebih banyak elemen selepas mencapai penghujung, anda tidak akan mempunyai apa-apa.

result = re.finditer(r'[a-z]+@[a-z]+\.[a-z]+', s)

for m in result:
    print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>
# <re.Match object; span=(13, 24), match='bbb@yyy.com'>
# <re.Match object; span=(26, 37), match='ccc@zzz.net'>

print(list(result))
# []

Gantikan bahagian yang sepadan: sub(), subn()

Menggunakan sub(), anda boleh menggantikan bahagian yang dipadankan dengan rentetan lain. Rentetan yang digantikan akan dikembalikan.

s = 'aaa@xxx.com, bbb@yyy.com, ccc@zzz.net'

result = re.sub(r'[a-z]+@[a-z]+\.com', 'new-address', s)
print(result)
# new-address, new-address, ccc@zzz.net

print(type(result))
# <class 'str'>

Apabila mengumpulkan dengan kurungan(), rentetan yang dipadankan boleh digunakan dalam rentetan yang diganti.

Secara lalai, yang berikut disokong: Ambil perhatian bahawa untuk rentetan biasa yang bukan rentetan mentah, garisan ke belakang mesti disenaraikan sebelum garisan ke belakang untuk melarikan diri dari garisan ke belakang.

\1Tanda kurung pertama
\2Tanda kurung kedua
\3Tanda kurung ketiga
result = re.sub(r'([a-z]+)@([a-z]+)\.com', r'\1@\2.net', s)
print(result)
# aaa@xxx.net, bbb@yyy.net, ccc@zzz.net

?P<xxx>
Jika anda menamakan kumpulan dengan menulis ini pada permulaan kurungan pola ungkapan biasa, anda boleh menentukannya menggunakan nama dan bukannya nombor, seperti yang ditunjukkan di bawah.
\g<xxx>

result = re.sub(r'(?P<local>[a-z]+)@(?P<SLD>[a-z]+)\.com', r'\g<local>@\g<SLD>.net', s)
print(result)
# aaa@xxx.net, bbb@yyy.net, ccc@zzz.net

Kiraan hujah menentukan bilangan maksimum penggantian. Hanya kiraan dari sebelah kiri akan diganti.

result = re.sub(r'[a-z]+@[a-z]+\.com', 'new-address', s, count=1)
print(result)
# new-address, bbb@yyy.com, ccc@zzz.net

subn() mengembalikan tuple rentetan yang digantikan (sama seperti nilai pulangan sub()) dan bilangan bahagian yang digantikan (nombor yang sepadan dengan corak).

result = re.subn(r'[a-z]+@[a-z]+\.com', 'new-address', s)
print(result)
# ('new-address, new-address, ccc@zzz.net', 2)

Kaedah menentukan hujah adalah sama seperti sub(). Anda boleh menggunakan bahagian yang dikumpulkan mengikut kurungan, atau tentukan bilangan hujah.

result = re.subn(r'(?P<local>[a-z]+)@(?P<SLD>[a-z]+)\.com', r'\g<local>@\g<SLD>.net', s)
print(result)
# ('aaa@xxx.net, bbb@yyy.net, ccc@zzz.net', 2)

result = re.subn(r'[a-z]+@[a-z]+\.com', 'new-address', s, count=1)
print(result)
# ('new-address, bbb@yyy.com, ccc@zzz.net', 1)

Memisahkan rentetan dengan corak ungkapan biasa: split()

split() membelah rentetan pada bahagian yang sepadan dengan corak dan mengembalikannya sebagai senarai.

Ambil perhatian bahawa padanan pertama dan terakhir akan mengandungi rentetan kosong pada permulaan dan akhir senarai yang terhasil.

s = '111aaa222bbb333'

result = re.split('[a-z]+', s)
print(result)
# ['111', '222', '333']

result = re.split('[0-9]+', s)
print(result)
# ['', 'aaa', 'bbb', '']

Argumen maxsplit menentukan bilangan maksimum belahan (kepingan). Hanya kiraan dari sebelah kiri akan dipecahkan.

result = re.split('[a-z]+', s, 1)
print(result)
# ['111', '222bbb333']

Metakarakter ungkapan biasa, jujukan khas dan kaveat dalam Python

Aksara meta ungkapan biasa utama (aksara khas) dan urutan khas yang boleh digunakan dalam modul Python 3 re adalah seperti berikut

metacharacterkandungan
.Mana-mana aksara tunggal selain daripada baris baharu (termasuk baris baharu dengan bendera DOTALL)
^Permulaan rentetan (juga sepadan dengan permulaan setiap baris dengan bendera MULTILINE)
$Penghujung rentetan (juga sepadan dengan penghujung setiap baris dengan bendera MULTILINE)
*Ulangi corak sebelumnya lebih daripada 0 kali
+Ulangi corak sebelumnya sekurang-kurangnya sekali.
?Ulangi corak sebelumnya 0 atau 1 kali
{m}Ulang pola sebelumnya m kali
{m, n}Corak terakhir.m~nulang
[]Satu set watak[]Padan dengan mana-mana satu daripada watak ini
|ATAUA|BPadan sama ada corak A atau B
urutan khaskandungan
\dNombor perpuluhan Unikod (terhad kepada nombor ASCII oleh bendera ASCII)
\D\dMaksudnya adalah sebaliknya.
\sAksara ruang putih Unikod (terhad kepada aksara ruang putih ASCII oleh bendera ASCII)
\S\sMaksudnya adalah sebaliknya.
\wAksara dan garis bawah perkataan Unikod (terhad kepada aksara abjad angka ASCII dan garis bawah mengikut bendera ASCII)
\W\wMaksudnya adalah sebaliknya.

Tidak semua daripada mereka disenaraikan dalam jadual ini. Lihat dokumentasi rasmi untuk senarai lengkap.

Juga ambil perhatian bahawa beberapa makna adalah berbeza dalam Python 2.

Menetapkan bendera

Seperti yang ditunjukkan dalam jadual di atas, beberapa aksara meta dan jujukan khas menukar mod mereka bergantung pada bendera.

Hanya bendera utama yang dilindungi di sini. Lihat dokumentasi rasmi untuk selebihnya.

Terhad kepada aksara ASCII: re.ASCII

\wIni juga akan memadankan kanji dwi-bait, aksara abjad angka, dsb. secara lalai untuk rentetan Python 3. Ia tidak bersamaan dengan yang berikut kerana ia bukan ungkapan biasa standard.[a-zA-Z0-9_]

m = re.match(r'\w+', '漢字ABC123')
print(m)
# <re.Match object; span=(0, 11), match='漢字ABC123'>

m = re.match('[a-zA-Z0-9_]+', '漢字ABC123')
print(m)
# None

Jika anda menentukan re.ASCII untuk bendera argumen dalam setiap fungsi, atau tambahkan bendera sebaris berikut pada permulaan rentetan corak ungkapan biasa, ia hanya akan sepadan dengan aksara ASCII (ia tidak akan sepadan dengan dua bait Jepun, aksara abjad angka, dsb. .).
(?a)
Dalam kes ini, dua berikut adalah setara.
\w#ERROR![a-zA-Z0-9_]

m = re.match(r'\w+', '漢字ABC123', flags=re.ASCII)
print(m)
# None

m = re.match(r'(?a)\w+', '漢字ABC123')
print(m)
# None

Perkara yang sama berlaku apabila menyusun dengan re.compile(). Gunakan bendera argumen atau bendera sebaris.

p = re.compile(r'\w+', flags=re.ASCII)
print(p)
# re.compile('\\w+', re.ASCII)

print(p.match('漢字ABC123'))
# None

p = re.compile(r'(?a)\w+')
print(p)
# re.compile('(?a)\\w+', re.ASCII)

print(p.match('漢字ABC123'))
# None

ASCII juga tersedia sebagai bentuk pendek semula. A. Anda boleh menggunakan sama ada.

print(re.ASCII is re.A)
# True

\W, bertentangan dengan \W, juga dipengaruhi oleh re.ASCII dan bendera sebaris.

m = re.match(r'\W+', '漢字ABC123')
print(m)
# None

m = re.match(r'\W+', '漢字ABC123', flags=re.ASCII)
print(m)
# <re.Match object; span=(0, 11), match='漢字ABC123'>

Seperti \w, dua yang berikut sepadan dengan kedua-dua aksara bait tunggal dan dua bait secara lalai, tetapi terhad kepada aksara bait tunggal jika re.ASCII atau bendera sebaris ditentukan.

  • Padankan nombor\d
  • Padan dengan ruang kosong\s
  • Padan dengan bukan nombor\D
  • Padan dengan mana-mana bukan ruang.\S
m = re.match(r'\d+', '123')
print(m)
# <re.Match object; span=(0, 3), match='123'>

m = re.match(r'\d+', '123')
print(m)
# <re.Match object; span=(0, 3), match='123'>

m = re.match(r'\d+', '123', flags=re.ASCII)
print(m)
# <re.Match object; span=(0, 3), match='123'>

m = re.match(r'\d+', '123', flags=re.ASCII)
print(m)
# None

m = re.match(r'\s+', ' ')  # full-width space
print(m)
# <re.Match object; span=(0, 1), match='\u3000'>

m = re.match(r'\s+', ' ', flags=re.ASCII)
print(m)
# None

Tidak sensitif huruf besar-besaran:re.IGNORECASE

Secara lalai, ia adalah sensitif huruf besar-besaran. Untuk memadankan kedua-duanya, anda perlu memasukkan kedua-dua huruf besar dan huruf kecil dalam corak.

re.IGNORECASEJika ini dinyatakan, ia akan dipadankan secara tidak sensitif huruf besar-besaran. Bersamaan dengan bendera i dalam ungkapan biasa standard.

m = re.match('[a-zA-Z]+', 'abcABC')
print(m)
# <re.Match object; span=(0, 6), match='abcABC'>

m = re.match('[a-z]+', 'abcABC', flags=re.IGNORECASE)
print(m)
# <re.Match object; span=(0, 6), match='abcABC'>

m = re.match('[A-Z]+', 'abcABC', flags=re.IGNORECASE)
print(m)
# <re.Match object; span=(0, 6), match='abcABC'>

Anda boleh menggunakan kurang daripada atau sama dengan.

  • bendera sebaris(?i)
  • singkatanre.I

Padankan permulaan dan penghujung setiap baris:re.MULTILINE

^Aksara meta dalam ungkapan biasa ini sepadan dengan permulaan rentetan.

Secara lalai, hanya permulaan keseluruhan rentetan dipadankan, tetapi yang berikut akan sepadan dengan permulaan setiap baris juga. Bersamaan dengan bendera m dalam ungkapan biasa standard.
re.MULTILINE

s = '''aaa-xxx
bbb-yyy
ccc-zzz'''

print(s)
# aaa-xxx
# bbb-yyy
# ccc-zzz

result = re.findall('[a-z]+', s)
print(result)
# ['aaa', 'xxx', 'bbb', 'yyy', 'ccc', 'zzz']

result = re.findall('^[a-z]+', s)
print(result)
# ['aaa']

result = re.findall('^[a-z]+', s, flags=re.MULTILINE)
print(result)
# ['aaa', 'bbb', 'ccc']

$Padan dengan hujung rentetan. Secara lalai, hanya hujung keseluruhan rentetan dipadankan.
re.MULTILINEJika anda menyatakan ini, ia juga akan sepadan dengan penghujung setiap baris.

result = re.findall('[a-z]+$', s)
print(result)
# ['zzz']

result = re.findall('[a-z]+$', s, flags=re.MULTILINE)
print(result)
# ['xxx', 'yyy', 'zzz']

Anda boleh menggunakan kurang daripada atau sama dengan.

  • bendera sebaris(?m)
  • singkatanre.M

Tentukan berbilang bendera

|Jika anda ingin mendayakan berbilang bendera pada masa yang sama, gunakan ini. Dalam kes bendera sebaris, setiap aksara mesti diikuti dengan huruf seperti yang ditunjukkan di bawah.
(?am)

s = '''aaa-xxx
漢漢漢-字字字
bbb-zzz'''

print(s)
# aaa-xxx
# 漢漢漢-字字字
# bbb-zzz

result = re.findall(r'^\w+', s, flags=re.M)
print(result)
# ['aaa', '漢漢漢', 'bbb']

result = re.findall(r'^\w+', s, flags=re.M | re.A)
print(result)
# ['aaa', 'bbb']

result = re.findall(r'(?am)^\w+', s)
print(result)
# ['aaa', 'bbb']

Perlawanan tamak dan tidak tamak

Ini adalah masalah umum dengan ungkapan biasa, bukan hanya masalah dengan Python, tetapi saya akan menulis mengenainya kerana ia cenderung membawa saya ke dalam masalah.

Secara lalai, yang berikut ialah padanan tamak, yang sepadan dengan rentetan terpanjang yang mungkin.

  • *
  • +
  • ?
s = 'aaa@xxx.com, bbb@yyy.com'

m = re.match(r'.+com', s)
print(m)
# <re.Match object; span=(0, 24), match='aaa@xxx.com, bbb@yyy.com'>

print(m.group())
# aaa@xxx.com, bbb@yyy.com

The ? selepas itu akan menghasilkan padanan yang tidak tamak, minimum, sepadan dengan rentetan terpendek yang mungkin.

  • *?
  • +?
  • ??
m = re.match(r'.+?com', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>

print(m.group())
# aaa@xxx.com

Ambil perhatian bahawa padanan tamak lalai mungkin sepadan dengan rentetan yang tidak dijangka.