Greedy vs. Reluctant vs Possessive Quantifiers

357

Saya menemukan tutorial yang sangat baik ini pada ekspresi reguler dan sementara saya secara intuitif memahami apa yang "serakah", "segan" dan "posesif" lakukan, tampaknya ada lubang serius dalam pemahaman saya.

Secara khusus, dalam contoh berikut:

Enter your regex: .*foo  // greedy quantifier
Enter input string to search: xfooxxxxxxfoo
I found the text "xfooxxxxxxfoo" starting at index 0 and ending at index 13.

Enter your regex: .*?foo  // reluctant quantifier
Enter input string to search: xfooxxxxxxfoo
I found the text "xfoo" starting at index 0 and ending at index 4.
I found the text "xxxxxxfoo" starting at index 4 and ending at index 13.

Enter your regex: .*+foo // possessive quantifier
Enter input string to search: xfooxxxxxxfoo
No match found.

Penjelasan menyebutkan memakan seluruh string input, surat telah dikonsumsi , pencocokan mundur , kejadian "foo" paling kanan telah dimuntahkan , dll.

Sayangnya, terlepas dari metafora yang bagus, saya masih tidak mengerti apa yang dimakan oleh siapa ... Apakah Anda tahu tutorial lain yang menjelaskan (ringkas) bagaimana mesin ekspresi reguler bekerja?

Atau, jika seseorang dapat menjelaskan dalam frasa yang agak berbeda pada paragraf berikut, itu akan sangat dihargai:

Contoh pertama menggunakan quantifier serakah. * Untuk menemukan "apa pun", nol atau lebih kali, diikuti dengan huruf "f" "o" "o". Karena quantifier itu serakah, bagian. * Dari ekspresi pertama-tama memakan seluruh string input. Pada titik ini, ekspresi keseluruhan tidak dapat berhasil, karena tiga huruf terakhir ("f" "o" "o") telah dikonsumsi ( oleh siapa? ). Jadi pencocokan perlahan-lahan mundur ( dari kanan ke kiri? ) Satu huruf pada satu waktu sampai kemunculan paling kanan dari "foo" telah dimuntahkan ( apa artinya ini? ), Pada titik mana pertandingan berhasil dan pencarian berakhir.

Contoh kedua, bagaimanapun, adalah enggan, jadi itu dimulai dengan mengkonsumsi pertama ( oleh siapa? ) "Tidak ada". Karena "foo" tidak muncul di awal string, terpaksa menelan ( siapa yang menelan?) Huruf pertama ("x"), yang memicu kecocokan pertama pada 0 dan 4. Uji harness kami melanjutkan proses sampai string input habis. Ia menemukan kecocokan lain pada 4 dan 13.

Contoh ketiga gagal menemukan kecocokan karena kuantifier bersifat posesif. Dalam kasus ini, seluruh string input dikonsumsi oleh. * +, ( Bagaimana? ) Tidak menyisakan apa pun untuk memuaskan "foo" di akhir ekspresi. Gunakan quantifier posesif untuk situasi di mana Anda ingin merebut semua sesuatu tanpa pernah mundur ( apa artinya mundur? ); itu akan mengungguli quantifier serakah yang setara dalam kasus di mana pertandingan tidak segera ditemukan.

Regex Rookie
sumber
22
Maksimal bilangan suka *, +dan ?yang serakah. Minimal bilangan suka *?, +?dan ??yang malas. Posesif bilangan suka *+, ++dan ?+yang lengket.
tchrist
6
Pertanyaan ini telah ditambahkan ke FAQ Ekspresi Reguler Overflow Stack , di bawah "Kuantifikasi> Selengkapnya tentang perbedaan ...".
aliteralmind
Yang menarik: Tutorial Java ™ - Perbedaan Antara Penamakan yang Serakah, Enggan, dan Posesif - Gulir ke bawah untuk melihat bagian.
Guy Coder

Jawaban:

495

Saya akan mencobanya.

Sebuah serakah quantifier pertandingan pertama sebanyak mungkin. Jadi .*cocok dengan seluruh string. Kemudian pencocokan mencoba untuk mencocokkan yang fberikut, tetapi tidak ada karakter yang tersisa. Jadi itu "backtracks", membuat quantifier serakah cocok dengan satu karakter kurang (meninggalkan "o" pada akhir string yang tak tertandingi). Itu masih belum cocok dengan fdi regex, jadi backtracks satu langkah lagi, membuat quantifier serakah cocok dengan satu karakter lagi (meninggalkan "oo" pada akhir string tidak tertandingi). Itu masih tidak cocok dengan fdi regex, sehingga backtracks satu langkah lagi (meninggalkan "foo" di akhir string tidak tertandingi). Sekarang, matcher akhirnya cocok dengan fdi regex,oococok juga. Keberhasilan!

Kuantitatif yang enggan atau "tidak rakus" pertama-tama cocok dengan sesedikit mungkin. Jadi .*tidak ada yang cocok pada awalnya, meninggalkan seluruh string yang tak tertandingi. Kemudian pencocokan mencoba untuk mencocokkan yang fberikut ini, tetapi bagian yang tidak cocok dari string dimulai dengan "x" sehingga tidak berfungsi. Jadi backtracks matcher, membuat quantifier non-serakah mencocokkan satu karakter lagi (sekarang cocok dengan "x", meninggalkan "fooxxxxxxfoo" tak tertandingi). Kemudian mencoba untuk mencocokkan f, yang berhasil, odan yang berikutnya odalam pertandingan regex juga. Keberhasilan!

Dalam contoh Anda, ia kemudian memulai proses dengan bagian yang tersisa dari string, "xxxxxxfoo", mengikuti proses yang sama.

Sebuah posesif pembilang adalah seperti quantifier serakah, tapi tidak backtrack. Jadi itu dimulai dengan .*mencocokkan seluruh string, tanpa meninggalkan apa pun yang tak tertandingi. Maka tidak ada yang tersisa untuk itu agar sesuai dengan fdi regex. Karena quantifier posesif tidak mundur, pertandingan gagal di sana.

Anomie
sumber
15
+1 Jawaban yang bagus. Saya hanya akan menambahkan: Baca membaca Menguasai Ekspresi Reguler (Edisi ke-3)
ridgerunner
@Anomie sedikit terlambat tetapi, di bagian posesif, saya pikir Anda maksud Jadi itu dimulai dengan .*+ (perhatikan "+")
RD
3
lalu apa yang dilakukan kuantifier posesif? jika tidak cocok dengan ini? (Maksud saya apa gunanya, jika Anda tidak dapat memiliki karakter setelahnya)
relipse
4
@relipse: Anda akan menggunakannya dalam situasi di mana Anda tahu bahwa mundur tidak akan membantu, mungkin tidak .*+cocok dengan semuanya. Misalnya, jika Anda memiliki pola [xyz]*foo, tidak mungkin melacak x, y, dan z yang cocok dengan [xyz]*bit akan memungkinkan foobit berikut cocok, sehingga Anda dapat mempercepatnya dengan membuatnya posesif.
Anomie
4
@oodboom, ada nol kasus (fakta matematika) di mana quantifiers posesif akan menghasilkan kecocokan yang tidak akan dihasilkan oleh quantif serakah sederhana. Kadang-kadang ada kasus di mana mereka akan menghasilkan tidak cocok ketika quantifier serakah akan menghasilkan pertandingan. Untuk SEMUA kasus lainnya (di mana rakus dan posesif menghasilkan hasil yang sama), quantifiers posesif memberikan keuntungan kinerja.
Wildcard
49

Hanya output latihan saya untuk memvisualisasikan adegan-

Gambar visual

SIslam
sumber
3
Kecuali saya pikir kasus terakhir, posesif, tidak boleh memiliki n melewati - hanya ambil seluruh string sekaligus.
perlakukan mod Anda dengan baik
@ phyzome saya pikir tidak apa-apa sekarang?
SIslam
1
Terima kasih atas penjelasan visualnya :)
Lars Moelleken
Dalam EXPRESSION .*?foo(), bukankah [f] [o] [o]persegi panjang harus berwarna kuning 5th pass?
tonix
1
@tonix ya! Pewarnaan kuning perlu dilakukan untuk bagian yang cocok dalam ekspresi .*?foodan .*+foo.
SIslam
24

Saya belum pernah mendengar istilah yang tepat 'memuntahkan' atau 'mundur' sebelumnya; frasa yang akan menggantikan ini adalah "backtracking", tetapi 'memuntahkan' sepertinya sama bagusnya dengan "konten yang telah diterima secara tentatif sebelum backtracking membuangnya lagi".

Hal penting untuk disadari tentang kebanyakan mesin regex adalah bahwa mereka mundur : mereka secara tentatif akan menerima kecocokan parsial yang potensial, sambil mencoba untuk mencocokkan seluruh isi regex. Jika regex tidak dapat sepenuhnya cocok pada upaya pertama, maka mesin regex akan mundur pada salah satu pertandingannya. Ini akan mencoba pencocokan *, +, ?, pergantian, atau {n,m}pengulangan berbeda, dan coba lagi. (Dan ya, proses ini bisa memakan waktu lama.)

Contoh pertama menggunakan quantifier serakah. * Untuk menemukan "apa pun", nol atau lebih kali, diikuti dengan huruf "f" "o" "o". Karena quantifier itu serakah, bagian. * Dari ekspresi pertama-tama memakan seluruh string input. Pada titik ini, ekspresi keseluruhan tidak dapat berhasil, karena tiga huruf terakhir ("f" "o" "o") telah dikonsumsi ( oleh siapa? ).

Tiga huruf terakhir, f, o, dan osudah dikonsumsi oleh awal .*porsi aturan. Namun, elemen berikutnya dalam regex,, ftidak memiliki apa pun yang tersisa di string input. Mesin akan dipaksa untuk mundur pada .*pertandingan awal , dan mencoba mencocokkan karakter semua-tapi-yang terakhir. (Mungkin cerdas dan mundur ke all-but-the-last-three, karena memiliki tiga istilah literal, tapi saya tidak mengetahui detail implementasi pada level ini.)

Jadi pencocokan secara perlahan mundur ( dari kanan ke kiri? ) Satu huruf pada satu waktu sampai kemunculan paling kanan dari "foo" telah dimuntahkan ( apa artinya ini? ), Di mana

Ini berarti foosudah tentatif termasuk saat pencocokan .*. Karena upaya itu gagal, mesin regex mencoba menerima satu karakter lebih sedikit di .*. Jika ada pertandingan sukses sebelum yang .*dalam contoh ini, maka mesin akan mungkin mencoba memperpendek .*pertandingan (dari kanan-ke-kiri, seperti yang Anda menunjukkan, karena merupakan kualifikasi serakah), dan jika tidak mampu pertandingan seluruh masukan, maka mungkin akan dipaksa untuk kembali mengevaluasi apa yang telah dicocokkan sebelum yang .*dalam contoh hipotetis saya.

arahkan kecocokan berhasil dan pencarian berakhir.

Contoh kedua, bagaimanapun, adalah enggan, jadi itu dimulai dengan mengkonsumsi pertama ( oleh siapa? ) "Tidak ada". Karena "foo"

Tidak ada awal yang dikonsumsi oleh .?*, yang akan mengkonsumsi jumlah sesingkat mungkin dari apa pun yang memungkinkan sisa regex untuk mencocokkan.

tidak muncul di awal string, itu dipaksa untuk menelan ( siapa yang menelan?)

Sekali lagi .?*mengkonsumsi karakter pertama, setelah mundur pada kegagalan awal untuk mencocokkan seluruh regex dengan pertandingan sesingkat mungkin. (Dalam hal ini, mesin regex memperpanjang pertandingan untuk .*?dari kiri ke kanan, karena .*?enggan.)

huruf pertama ("x"), yang memicu kecocokan pertama pada 0 dan 4. Uji harness kami melanjutkan proses sampai string input habis. Ia menemukan kecocokan lain pada 4 dan 13.

Contoh ketiga gagal menemukan kecocokan karena kuantifier bersifat posesif. Dalam hal ini, seluruh string input dikonsumsi oleh. * +, ( Bagaimana? )

A .*+akan mengkonsumsi sebanyak mungkin, dan tidak akan mundur untuk menemukan kecocokan baru ketika regex secara keseluruhan gagal menemukan kecocokan. Karena bentuk posesif tidak melakukan backtracking, Anda mungkin tidak akan melihat banyak kegunaan dengan .*+, melainkan dengan kelas karakter atau pembatasan serupa: account: [[:digit:]]*+ phone: [[:digit:]]*+.

Ini secara drastis dapat mempercepat pencocokan regex, karena Anda memberi tahu mesin regex bahwa ia tidak boleh mundur dari pencocokan potensial jika input tidak cocok. (Jika Anda harus menulis semua kode yang cocok dengan tangan, ini akan sama dengan tidak pernah menggunakan putc(3)untuk 'mendorong kembali' karakter input. Ini akan sangat mirip dengan kode naif yang mungkin ditulis pada percobaan pertama. Kecuali mesin regex adalah jauh lebih baik daripada satu karakter push-back, mereka dapat memundurkan semua kembali ke nol dan coba lagi. :)

Tetapi lebih dari potensi percepatan, ini juga dapat membuat Anda menulis regex yang cocok dengan apa yang Anda butuhkan untuk mencocokkan. Saya mengalami masalah dengan contoh yang mudah :) tetapi menulis regex menggunakan quantif vs serakah quantifiers dapat memberi Anda kecocokan yang berbeda, dan satu atau yang lain mungkin lebih tepat.

tidak meninggalkan apa pun yang tersisa untuk memuaskan "foo" di akhir ungkapan. Gunakan quantifier posesif untuk situasi di mana Anda ingin merebut semua sesuatu tanpa pernah mundur ( apa artinya mundur? ); itu akan mengungguli

"Mundur" dalam konteks ini berarti "mundur" - membuang pertandingan parsial sementara untuk mencoba pertandingan parsial lain, yang mungkin berhasil atau tidak.

quantifier serakah setara dalam kasus di mana pertandingan tidak segera ditemukan

sarnold
sumber
2
Saya menduga bahwa tidak pernah ada kasus di mana quantifier posesif akan cocok dengan sesuatu yang quantifier serakah tidak akan. Saya percaya bahwa yang berikut membuktikannya: Kuantitatif serakah selalu cocok sebanyak mungkin, lalu mundur jika tidak dapat menemukan kecocokan. Kuantif posesif cocok sebanyak mungkin, lalu berhenti jika tidak dapat menemukan kecocokan. Jadi mungkin ada sesuatu yang cocok dengan quantifier serakah yang quantifier posesif tidak akan, tetapi tidak sebaliknya, karena mereka berdua mencari "pohon" dalam urutan yang sama, quantifier posesif hanya menyerah dengan lebih mudah. ;)
Wildcard
2
Dikonfirmasi: "Untuk itulah pengelompokan atomik dan penjumlahan posesif adalah: efisiensi dengan tidak mengundurkan diri." from regular-expressions.info Jadi pernyataan dalam jawaban ini "Tetapi lebih dari potensi percepatan, ini juga dapat membuat Anda menulis regex yang cocok dengan apa yang Anda butuhkan untuk mencocokkan." sebenarnya tidak cukup akurat.
Wildcard
1
@Wildcard, terima kasih atas komentarnya; itu mungkin menjelaskan mengapa saya kesulitan memberikan contoh. Hehe.
sarnold
19

http://swtch.com/~rsc/regexp/regexp1.html

Saya tidak yakin itu penjelasan terbaik di internet, tetapi itu ditulis dengan cukup baik dan detail yang tepat, dan saya terus kembali ke sana. Anda mungkin ingin memeriksanya.

Jika Anda menginginkan tingkat yang lebih tinggi (penjelasan yang kurang rinci), untuk ekspresi reguler sederhana seperti yang Anda lihat, mesin ekspresi reguler berfungsi dengan menelusuri ulang. Pada dasarnya, ia memilih ("makan") bagian dari string dan mencoba untuk mencocokkan ekspresi reguler terhadap bagian itu. Jika cocok, bagus. Jika tidak, mesin mengubah pilihan bagian string dan mencoba mencocokkan regexp dengan bagian itu, dan seterusnya, hingga dicoba setiap pilihan yang memungkinkan.

Proses ini digunakan secara rekursif: dalam usahanya untuk mencocokkan string dengan ekspresi reguler yang diberikan, mesin akan membagi ekspresi reguler menjadi potongan-potongan dan menerapkan algoritma untuk setiap bagian secara individual.

Perbedaan antara quantif serakah, enggan, dan posesif masuk ketika mesin membuat pilihan bagian tali mana yang harus dicocokkan, dan bagaimana memodifikasi pilihan itu jika tidak bekerja pertama kali. Aturannya adalah sebagai berikut:

  • Kuantitatif serakah memberi tahu mesin untuk memulai dengan seluruh string (atau setidaknya, semua yang belum cocok dengan bagian sebelumnya dari ekspresi reguler) dan periksa apakah cocok dengan regexp. Jika demikian, bagus; mesin dapat melanjutkan sisa regexp. Jika tidak, ia mencoba lagi, tetapi memangkas satu karakter (yang terakhir) dari bagian string yang akan diperiksa. Jika itu tidak berhasil, itu memangkas karakter lain, dll. Jadi quantifier rakus memeriksa kemungkinan yang cocok dalam urutan dari terpanjang ke terpendek.

  • Pengukur enggan memberi tahu mesin untuk memulai dengan seutas tali yang sesingkat mungkin. Jika cocok, mesin dapat melanjutkan; jika tidak, ia menambahkan satu karakter ke bagian string yang sedang diperiksa dan mencobanya, dan seterusnya sampai menemukan kecocokan atau seluruh string telah digunakan. Jadi quantifier yang enggan memeriksa kemungkinan kecocokan secara berurutan dari yang terpendek ke yang terpanjang.

  • Sebuah quantifier posesif adalah seperti quantifier serakah pada upaya pertama: itu memberitahu mesin untuk memulai dengan memeriksa seluruh string. Perbedaannya adalah bahwa jika tidak berhasil, quantifier posesif melaporkan bahwa kecocokan gagal saat itu juga. Mesin tidak mengubah bagian dari string yang sedang dilihat, dan tidak membuat upaya lagi.

Inilah sebabnya mengapa kecocokan kuantifier gagal dalam contoh Anda: .*+dicentang terhadap seluruh string, yang cocok, tetapi kemudian mesin melanjutkan untuk mencari karakter tambahan foosetelah itu - tetapi tentu saja tidak menemukannya, karena Anda Sudah ada di akhir string. Jika itu adalah pengukur serakah, itu akan mundur dan mencoba membuat .*satu - satunya yang cocok hingga karakter berikutnya-terakhir, kemudian hingga karakter ketiga hingga terakhir, kemudian hingga karakter keempat hingga terakhir, yang berhasil karena baru kemudian ada fookiri setelah .*"makan" bagian awal dari string.

David Z
sumber
1
Itu sumber yang bagus. Saya suka diagram mesin negara. :)
Regex Rookie
@Regex Rookie: senang Anda menyukainya :) Setelah melihat-lihat situs itu, saya pikir saya harus menjelaskan bahwa tujuannya adalah untuk mempromosikan implementasi alternatif dari mesin ekspresi reguler. Algoritma backtracking I (sebagian) dan jawaban lain yang dijelaskan adalah cara lambat ; ini adalah algoritma yang sepenuhnya terpisah dari ide NFA / DFA yang dijelaskan di halaman web. Mundur hanya lebih mudah untuk dipahami, itulah sebabnya mengapa regexps biasanya dijelaskan kepada pemula.
David Z
@ David Zaslavsky: Penjelasan yang bagus. Komentar Anda dalam tanda kurung di "Sebuah pengukur serakah memberi tahu mesin untuk memulai dengan seluruh string (atau setidaknya, semua itu belum cocok dengan bagian sebelumnya dari ekspresi reguler)" adalah penting. Mereka juga berlaku untuk quantifiers enggan dan posesif. Ini membuat penjelasan Anda kompatibel dengan apa yang terjadi ketika kami mengubah pola contoh kami dari (". * Foo"; ". *? Foo"; dan ". * + Foo") menjadi ("foo. *"; "Foo. *? "; dan" foo. * + ").
John Bentley
Sebenarnya, xfooxxxxxxfoo tidak cocok. * Foo dalam normal (arti ilmu komputer) dari ekspresi reguler. NFA akan menjadi sebuah negara di mana ia berbelit-belit dengan karakter apa pun dan kemudian dapat melompat ke foo. DFA akan menjadi terjemahan langsung dari NFA itu. Itu bisa dilakukan di 8 negara.
user4951
@ Jim Thio ya, karena itu bukan quantifier posesif.
David Z
13

Inilah yang saya ambil menggunakan posisi Sel dan Indeks (Lihat diagram di sini untuk membedakan Sel dari Indeks).

Serakah - Cocokkan sebanyak mungkin dengan quantifier serakah dan seluruh regex. Jika tidak ada kecocokan, mundur pada quantifier serakah.

Input String: xfooxxxxxxfoo
Regex:. * Foo

Regex di atas memiliki dua bagian:
(i) '. *' Dan
(ii) 'foo'

Setiap langkah di bawah ini akan menganalisis dua bagian. Komentar tambahan untuk kecocokan dengan 'Lulus' atau 'Gagal' dijelaskan dalam kurung kurawal.

Langkah 1:
(i). * = Xfooxxxxxxfoo - PASS ('. *' Adalah quantifier serakah dan akan menggunakan seluruh String Input)
(ii) foo = Tidak ada karakter yang tersisa untuk dicocokkan setelah indeks 13 - FAIL
Match gagal.

Langkah 2:
(i). * = Xfooxxxxxxfo - PASS (Mundur dari pengukur serakah '. *')
(Ii) foo = o - GAGAL
Pertandingan gagal.

Langkah 3:
(i). * = Xfooxxxxxxf - PASS (Mundur dari pengukur serakah '. *')
(Ii) foo = oo - GAGAL
Pertandingan gagal.

Langkah 4:
(i). * = Xfooxxxxxx - PASS (Mundur dari pengukur serakah '. *')
(Ii) foo = foo -
Laporan LULUS PERTANDINGAN

Hasil: 1 match (es)
Saya menemukan teks "xfooxxxxxxfoo" mulai dari indeks 0 dan berakhir pada indeks 13.

Enggan - Cocokkan sesedikit mungkin dengan kuantifier enggan dan cocokkan seluruh regex. jika tidak ada kecocokan, tambahkan karakter ke quantifier yang enggan.

Input String: xfooxxxxxxfoo
Regex:. *? Foo

Regex di atas memiliki dua bagian:
(i) '. *?' dan
(ii) 'foo'

Langkah 1:.
*? = '' (kosong) - LULUS (Cocokkan sesedikit mungkin dengan kuantifier enggan '. *?'. Indeks 0 memiliki '' adalah kecocokan.)
foo = xfo - FAIL (Sel 0,1,2 - yaitu indeks antara 0 dan 3)
Pertandingan gagal.

Langkah 2:.
*? = x - LULUS (Tambahkan karakter ke quantifier enggan '. *?'. Sel 0 memiliki 'x' adalah kecocokan.)
foo = foo - LULUS
Laporan MATCH

Langkah 3:.
*? = '' (kosong) - LULUS (Cocokkan sesedikit mungkin dengan kuantifier enggan '. *?'. Indeks 4 memiliki '' adalah kecocokan.)
foo = xxx - GAGAL (Sel 4,5,6 - yaitu indeks antara 4 dan 7)
Pertandingan gagal.

Langkah 4:.
*? = x - LULUS (Tambahkan karakter ke kuantifier enggan '. *?'. Sel 4.)
foo = xxx - FAIL (Sel 5,6,7 - yaitu indeks antara 5 dan 8)
Pencocokan gagal.

Langkah 5:.
*? = xx - LULUS (Tambahkan karakter ke kuantifier enggan '. *?'. Sel 4 sampai 5.)
foo = xxx - GAGAL (Sel 6,7,8 - yaitu indeks antara 6 dan 9)
Pencocokan gagal.

Langkah 6:.
*? = xxx - LULUS (Tambahkan karakter ke kuantifier enggan '. *?'. Sel 4 sampai 6.)
foo = xxx - GAGAL (Sel 7,8,9 - yaitu indeks antara 7 dan 10)
Pencocokan gagal.

Langkah 7:.
*? = xxxx - LULUS (Tambahkan karakter ke kuantifier enggan '. *?'. Sel 4 sampai 7.)
foo = xxf - FAIL (Sel 8,9,10 - yaitu indeks antara 8 dan 11)
Pencocokan gagal.

Langkah 8:.
*? = xxxxx - LULUS (Tambahkan karakter ke kuantifier enggan '. *?'. Sel 4 sampai 8.)
foo = xfo - FAIL (Sel 9,10,11 - yaitu indeks antara 9 dan 12)
Pencocokan gagal.

Langkah 9:.
*? = xxxxxx - LULUS (Tambahkan karakter ke kuantifier enggan '. *?'. Sel 4 sampai 9.)
foo = foo - LULUS (Sel 10,11,12 - yaitu indeks antara 10 dan 13)
Laporkan MATCH

Langkah 10:.
*? = '' (kosong) - LULUS (Cocokkan sesedikit mungkin dengan quantifier yang enggan '. *?'. Indeks 13 kosong.)
foo = Tidak ada karakter yang tersisa untuk dicocokkan - GAGAL (Tidak ada apa pun setelah indeks 13 yang cocok)
Cocok gagal.

Hasil: 2 match (es)
Saya menemukan teks "xfoo" mulai dari indeks 0 dan berakhir pada indeks 4.
Saya menemukan teks "xxxxxxfoo" mulai dari indeks 4 dan berakhir pada indeks 13.

Posesif - Cocokkan sebanyak mungkin dengan kuantifer posesif dan cocokkan dengan seluruh regex. JANGAN mundur.

Input String: xfooxxxxxxfoo
Regex:. * + Foo

Regex di atas memiliki dua bagian: '. * +' Dan 'foo'.

Langkah 1:.
* + = Xfooxxxxxxfoo - PASS (Cocokkan sebanyak mungkin dengan quantifier posesif '. *')
Foo = Tidak ada karakter yang tersisa untuk dicocokkan - GAGAL (Tidak ada yang cocok dengan indeks 13)
Pencocokan gagal.

Catatan: Mundur tidak diizinkan.

Hasil: 0 pertandingan

raka
sumber
1

Serakah: "cocok dengan urutan karakter terpanjang yang mungkin"

Enggan: "cocok dengan urutan karakter yang sesingkat mungkin"

Posesif: Ini agak aneh karena TIDAK (berbeda dengan serakah dan enggan) mencoba menemukan kecocokan untuk seluruh regex.

Omong-omong: Tidak ada implementasi pencocokan pola regex yang akan menggunakan backtracking. Semua pencocokan pola kehidupan nyata sangat cepat - hampir tidak tergantung pada kompleksitas ekspresi reguler!

Tilo Koerbs
sumber
Sejauh yang saya tahu sebagian besar implementasi penggunaan umum sekarang penuh dengan fitur sehingga tidak mungkin untuk tidak menggunakan backtracking. Jadi secara teori mereka harus sangat (eksponensial) lambat untuk beberapa kasus. Tetapi untuk sebagian besar kasus ada optimasi khusus yang dibangun ke dalam pencocokan pola.
Robert
0

Kuantifikasi Serakah melibatkan pencocokan pola menggunakan semua karakter string yang tidak divalidasi yang tersisa selama iterasi. Karakter yang tidak divalidasi mulai dalam urutan aktif . Setiap kali pertandingan tidak terjadi, karakter di akhir dikarantina dan cek dilakukan lagi.

Ketika hanya kondisi utama dari pola regex dipenuhi oleh urutan aktif, upaya dilakukan untuk memvalidasi kondisi yang tersisa terhadap karantina. Jika validasi ini berhasil, karakter yang cocok dalam karantina divalidasi dan sisa karakter yang tidak cocok tetap tidak divalidasi dan akan digunakan ketika proses dimulai lagi di iterasi berikutnya.

Alur karakter dari urutan aktif ke karantina. Perilaku yang dihasilkan adalah sebanyak mungkin urutan asli termasuk dalam kecocokan.

Kuantitatif enggan sebagian besar sama dengan kualifikasi serakah kecuali aliran karakter adalah sebaliknya - yaitu, mereka mulai di karantina dan mengalir ke urutan aktif . Perilaku yang dihasilkan adalah bahwa sesedikit mungkin urutan asli termasuk dalam kecocokan.

Kuantifikasi Posesif tidak memiliki karantina dan memasukkan semuanya dalam urutan aktif yang tetap .

Chad Philip Johnson
sumber