2.36. Grup dan jangkar¶
Sebuah pola bisa melakukan lebih dari sekadar mengatakan "string ini cocok" -- ia dapat memisahkan bagian yang cocok dan menyerahkan masing-masing ke aplikasi berdasarkan nama. Tanda kurung di sekitar bagian pola menjadikannya grup tangkapan; objek pencocokan kemudian mengekspos setiap grup sebagai substring terpisah.
2.36.1. Grup tangkapan¶
Bungkus bagian mana pun dari sebuah pola dalam (...) untuk menangkap apa yang cocok:
>>> import re
>>> m = re.search(r'temp (\d+) at (\d+)s', 'temp 42 at 137s ok')
>>> m.group(0)
'temp 42 at 137s'
>>> m.group(1)
'42'
>>> m.group(2)
'137'
Grup 0 selalu merupakan keseluruhan pencocokan.
Grup 1, 2, ... adalah substring yang ditangkap, dinomori dari kiri ke kanan berdasarkan tanda kurung pembuka mereka.
Memanggil
match.group()dengan indeks melebihi grup terakhir akan memunculkanIndexError.
Pola umum adalah "cocokkan struktur yang diketahui, tangkap bagian variabel sebagai int":
def parse_temp(line):
m = re.search(r'temp (\d+) at (\d+)s', line)
if not m:
return None
return int(m.group(1)), int(m.group(2))
2.36.2. Grup non-tangkapan¶
Tanda kurung juga mengelompokkan sub-ekspresi sehingga kuantifier dapat diterapkan pada seluruh grup. Itulah satu-satunya tujuan pengelompokan dalam r'(ab)+' -- "satu atau lebih dari ab". Fakta bahwa ab muncul sebagai grup 1 adalah efek samping.
Untuk mengelompokkan tanpa menangkap, gunakan (?:...)
>>> re.search(r'(?:ab)+', 'xababy').group(0)
'abab'
Grup non-tangkapan menjaga nomor grup tetap rapi ketika sebuah pola menggunakan pengelompokan untuk struktur tetapi tidak perlu menarik setiap bagian.
2.36.3. Jangkar¶
Jangkar tidak mencocokkan karakter -- mereka mencocokkan sebuah posisi.
^-- awal string.$-- akhir string.
Jangkar inilah yang membuat re.match() dan re.search() berperilaku berbeda. re.match(p, s) sama dengan re.search('^' + p, s): ini memaksa pola untuk dimulai pada posisi 0. Menambahkan $ di akhir pola kemudian membuat pola mencocokkan seluruh string dan tidak ada yang lain:
>>> re.search(r'^\d+$', '12345')
<match num=1>
>>> re.search(r'^\d+$', '12345 ok') is None
True
^ dan $ dalam MicroPython re selalu berarti awal dan akhir dari seluruh string yang diteruskan ke re.search(). Tidak ada flag re.MULTILINE untuk membuatnya cocok pada setiap baris baru yang tertanam, dan $ juga tidak mencocokkan posisi sebelum \n di akhir -- itu harus benar-benar akhir dari input. Untuk mendapatkan perilaku per baris, pisahkan input berdasarkan baris baru terlebih dahulu dan jalankan pola pada setiap baris.
2.36.4. Kumpulan karakter¶
Tanda kurung siku mendefinisikan kumpulan karakter yang eksplisit. Pencocokan mengonsumsi tepat satu karakter dari kumpulan.
[abc]-- salah satu daria,b,c.[a-z]-- satu karakter dalam rentanga-z(inklusif).[a-zA-Z0-9]-- huruf atau angka. Tiga rentang dikombinasikan.[^abc]-- bukan salah satu daria,b,c.^hanya menegasikan ketika itu karakter pertama di dalam tanda kurung.
Contoh:
>>> re.search(r'[A-F0-9]{6}', 'colour #1a2b3c rest').group(0)
'1A2B3C'
>>> re.search(r'[A-F0-9]{6}', 'colour #1a2b3c rest') is None
True
Panggilan pertama mengembalikan None dalam praktiknya karena teks literal menggunakan huruf kecil. MicroPython re tidak memiliki flag re.IGNORECASE -- untuk mencocokkan tanpa memperhatikan huruf besar/kecil, tulis kedua kasus ke dalam kumpulan:
>>> re.search(r'[A-Fa-f0-9]{6}', 'colour #1a2b3c rest').group(0)
'1a2b3c'
Pintasan kelas (\d, \s, \w, dan bentuk negatifnya) juga dapat digunakan di dalam [...]: [\w-] adalah "karakter kata atau tanda hubung literal."
2.36.5. Kuantifier serakah vs malas¶
Kuantifier *, +, ?, dan {m,n} secara default bersifat serakah -- mereka mencocokkan sebanyak mungkin karakter yang masih diizinkan oleh sisa pola. Seringkali itu persis yang diinginkan; terkadang tidak:
>>> re.search(r'<(.+)>', 'a <b> <c> d').group(1)
'b> <c'
.+ yang serakah mengambil semua jalan hingga > terakhir. Menambahkan ? membuat kuantifier menjadi malas -- ia mencocokkan sesedikit mungkin:
>>> re.search(r'<(.+?)>', 'a <b> <c> d').group(1)
'b'
Bentuk malas berhenti di > pertama. Kuantifier malas sering muncul saat mengekstrak pembatas seimbang dari sebuah string.
2.36.6. Backreference dalam substitusi¶
re.sub() dapat merujuk kembali ke grup yang ditangkap dalam string pengganti melalui \1, \2, ... Substitusi menulis ulang setiap pencocokan menggunakan bagian yang ditangkap:
>>> re.sub(r'(\d+)\.(\d+)', r'\2.\1', 'swap 12.34 and 5.6')
'swap 34.12 and 6.5'
Setiap pencocokan menangkap dua angka, dan penggantian menukarnya. \g<1> adalah sintaksis alternatif untuk hal yang sama -- berguna ketika karakter berikutnya dalam penggantian adalah angka (r'\g<1>0' untuk menambahkan nol literal ke grup 1 daripada membaca "grup 10").
2.36.7. Yang tidak tersedia¶
Pengingat tentang apa yang tidak didukung oleh MicroPython re, jika sebuah pola dari CPython muncul di sini dan mengejutkan Anda:
Lookahead
(?=...)dan lookbehind(?<=...)-- tidak diimplementasikan.Grup bernama
(?P<name>...)dan backreference bernama(?P=name)-- tidak diimplementasikan.Konstanta flag seperti
re.IGNORECASE,re.MULTILINE,re.DOTALL-- tidak didukung. Buat kumpulan case-insensitive atau pisahkan input sendiri terlebih dahulu.Metode
match.groups(),match.span(),match.start(), danmatch.end()bergantung pada level ROM yang tidak diaktifkan oleh papan OpenMV yang dikirimkan. Kode yang bergantung pada metode tersebut tidak akan berjalan di kamera.
Dengan pola, grup, dan jangkar, toolset regex di kamera cukup kecil untuk dipelajari dalam satu sesi dan cukup kaya untuk melakukan segalanya kecuali penguraian yang peka konteks.