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

So8res
sumber

Jawaban:

209

Anda mencari yang sangat kuat *?

Dari dokumen, Serakah versus Non-Serakah

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

Trey Stout
sumber
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>'.

Paolo Bergantino
sumber
14

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

Zitrax
sumber
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.

Chas. Owens
sumber
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)
ojrac
sumber
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'
David Berger
sumber
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.

Daleks
sumber