Python regex non-serakah


150

Bagaimana cara membuat regex python "(.*)"seperti itu, mengingat "a (b) c (d) e"cocok python "b"bukan "b) c (d"?

Saya tahu bahwa saya bisa menggunakan "[^)]"bukan ".", tapi saya mencari solusi yang lebih umum yang membuat regex saya sedikit lebih bersih. Apakah ada cara untuk memberi tahu python "hei, cocokkan ini secepat mungkin"?

Jawaban:


209

Anda mencari yang sangat kuat *?

Dari dokumen, Serakah versus Non-Serakah

kualifikasi non-serakah *?, +?, ??, atau {m,n}?[...] pertandingan sebagai sedikit teks mungkin.


Menurut Internet Archive, semua tautan yang ditunjukkan adalah salinan modul dokumen Python "re", jadi tautan Trey juga berfungsi dengan baik.
spiffytech

2
apa nama bahasa Inggris yang umum untuk ini *??
Trevor Boyd Smith

Karakter wildcard @Trevor Boyd Smith
Serge

3
Ini disebut kualifikasi "tidak serakah"
brunetton

65
>>> x = "a (b) c (d) e"
>>> re.search(r"\(.*\)", x).group()
'(b) c (d)'
>>> re.search(r"\(.*?\)", x).group()
'(b)'

Menurut dokumen :

Kualifikasi ' *', ' +', dan ' ?' semuanya serakah; mereka mencocokkan teks sebanyak mungkin. Terkadang perilaku ini tidak diinginkan; jika RE <.*>dicocokkan dengan ' <H1>title</H1>', itu akan cocok dengan seluruh string, dan bukan hanya ' <H1>'. Menambahkan ' ?' setelah kualifikasi membuatnya melakukan pertandingan dengan cara yang tidak serakah atau minimal; sesedikit mungkin karakter akan dicocokkan. Menggunakan .*?dalam ekspresi sebelumnya hanya akan cocok dengan ' <H1>'.


14

Tidak akan \\(.*?\\)bekerja Itu adalah sintaksis yang tidak rakus.


5

Seperti yang orang lain katakan menggunakan? modifier pada * quantifier akan menyelesaikan masalah langsung Anda, tetapi hati-hati, Anda mulai menyimpang ke daerah di mana regex berhenti bekerja dan Anda membutuhkan parser sebagai gantinya. Misalnya, string "(foo (bar)) baz" akan menyebabkan masalah bagi Anda.


5

Menggunakan pertandingan yang tidak cocok adalah awal yang baik, tetapi saya juga menyarankan Anda mempertimbangkan kembali penggunaan .*- bagaimana dengan ini?

groups = re.search(r"\([^)]*\)", x)

3

Apakah Anda ingin mencocokkan "(b)"? Lakukan seperti yang disarankan Zitrax dan Paolo. Apakah Anda ingin mencocokkan "b"? Melakukan

>>> x = "a (b) c (d) e"
>>> re.search(r"\((.*?)\)", x).group(1)
'b'

0

Untuk mulai dengan, saya tidak menyarankan menggunakan "*" di regex. Ya, saya tahu, ini adalah pembatas multi-karakter yang paling banyak digunakan, tetapi bagaimanapun juga itu adalah ide yang buruk. Ini karena, meskipun cocok dengan jumlah pengulangan untuk karakter itu, "any" termasuk 0, yang biasanya merupakan sesuatu yang Anda ingin lontarkan kesalahan sintaksinya, tidak terima. Alih-alih, saya sarankan menggunakan +tanda, yang cocok dengan pengulangan panjang> 1. Terlebih lagi, dari apa yang saya lihat, Anda berhadapan dengan ekspresi yang dipatenkan dengan panjang tetap. Akibatnya, Anda mungkin dapat menggunakan {x, y}sintaks untuk secara spesifik menentukan panjang yang diinginkan.

Namun, jika Anda benar-benar membutuhkan pengulangan yang tidak rakus, saya sarankan berkonsultasi dengan yang mahakuasa ?. Ini, ketika ditempatkan setelah pada akhir setiap specifier pengulangan regex, akan memaksa bagian dari regex untuk menemukan jumlah teks sesedikit mungkin.

Yang sedang berkata, saya akan sangat berhati-hati dengan ?itu, seperti Sonic Obeng di Dr Who, memiliki kecenderungan untuk melakukan, bagaimana saya harus mengatakannya, "sedikit" hal-hal yang tidak diinginkan jika tidak hati-hati dikalibrasi. Misalnya, untuk menggunakan input contoh Anda, ini akan mengidentifikasi ((1)(perhatikan kurangnya rparen kedua) sebagai kecocokan.

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.