Apa perbedaan antara .*? dan. * ekspresi reguler?

151

Saya mencoba membagi string menjadi dua bagian menggunakan regex. String tersebut diformat sebagai berikut:

text to extract<number>

Saya telah menggunakan (.*?)<dan <(.*?)>mana yang berfungsi dengan baik tetapi setelah membaca sedikit ke dalam regex, saya baru saja mulai bertanya-tanya mengapa saya membutuhkan ?ekspresi dalam. Saya hanya melakukannya seperti itu setelah menemukannya melalui situs ini jadi saya tidak begitu yakin apa bedanya.

Doug
sumber

Jawaban:

186

Ini adalah perbedaan antara bilangan serakah dan non-serakah.

Pertimbangkan masukannya 101000000000100.

Menggunakan 1.*1, *itu serakah - itu akan cocok sampai akhir, dan kemudian mundur sampai bisa cocok 1, meninggalkan Anda dengan 1010000000001.
.*?tidak serakah. *tidak akan cocok, tetapi kemudian akan mencoba untuk mencocokkan karakter tambahan hingga cocok 1, akhirnya cocok 101.

Semua bilangan memiliki mode non-serakah: .*?, .+?, .{2,6}?, dan bahkan .??.

Dalam kasus Anda, pola yang serupa bisa jadi <([^>]*)>- mencocokkan apa pun kecuali tanda yang lebih besar dari (secara tegas, ini cocok dengan nol atau lebih karakter selain >di antara <dan >).

Lihat Lembar Cheat Pengukur .

Kobi
sumber
Ah bagus, aku suka yang terakhir dari apa pun kecuali tanda>!
Doug
1
Dapatkah Anda menjelaskan atau menunjukkan contoh bagaimana orang serakah ?berbeda dari yang tidak serakah ???
AdrianHHH
4
Tentu. Untuk string "abc", regex /\w\w?\w/akan cocok dengan string lengkap "abc"- karena ?serakah. /\w\w??\w/malas - itu hanya akan cocok "ab". Itu hanya akan mundur dan cocok "abc"jika gagal nanti.
Kobi
190

Tentang serakah vs tidak serakah

Pengulangan dalam regex secara default serakah : mereka mencoba mencocokkan repetisi sebanyak mungkin, dan ketika ini tidak berhasil dan mereka harus mundur, mereka mencoba untuk mencocokkan satu repetisi lebih sedikit pada satu waktu, sampai kecocokan dari keseluruhan pola ditemukan. Akibatnya, ketika pertandingan akhirnya terjadi, pengulangan serakah akan cocok sebagai banyak repetisi sebanyak mungkin.

The ?as a repetition quantifier mengubah perilaku ini menjadi tidak serakah , juga disebut enggan ( misalnya di Java ) (dan terkadang "malas"). Sebaliknya, pengulangan ini pertama-tama akan mencoba mencocokkan pengulangan sesedikit mungkin, dan ketika ini tidak berhasil dan mereka harus mundur, mereka mulai mencocokkan satu reptil lagi. Akibatnya, ketika pertandingan akhirnya terjadi, pengulangan yang enggan akan cocok dengan pengulangan sesedikit mungkin.

Referensi


Contoh 1: Dari A ke Z

Mari kita bandingkan dua pola ini: A.*Zdan A.*?Z.

Diberikan masukan berikut:

eeeAiiZuuuuAoooZeeee

Pola menghasilkan kecocokan berikut:

Pertama mari kita fokus pada apa A.*Z. Ketika cocok dengan yang pertama A, yang .*, menjadi serakah, pertama mencoba untuk mencocokkan sebanyak .mungkin.

eeeAiiZuuuuAoooZeeee
   \_______________/
    A.* matched, Z can't match

Karena Ztidak cocok, mesin mundur, dan .*kemudian harus cocok satu lebih sedikit .:

eeeAiiZuuuuAoooZeeee
   \______________/
    A.* matched, Z still can't match

Ini terjadi beberapa kali lagi, sampai akhirnya kita sampai pada ini:

eeeAiiZuuuuAoooZeeee
   \__________/
    A.* matched, Z can now match

Sekarang Zbisa cocok, jadi pola keseluruhan cocok:

eeeAiiZuuuuAoooZeeee
   \___________/
    A.*Z matched

Sebaliknya, pengulangan enggan di A.*?Zpertandingan pertama sesedikit .mungkin, dan kemudian mengambil lebih banyak .bila perlu. Ini menjelaskan mengapa ia menemukan dua kecocokan dalam masukan.

Berikut adalah representasi visual dari apa yang cocok kedua pola tersebut:

eeeAiiZuuuuAoooZeeee
   \__/r   \___/r      r = reluctant
    \____g____/        g = greedy

Contoh: Alternatif

Dalam banyak aplikasi, dua kecocokan pada input di atas adalah yang diinginkan, sehingga .*?digunakan enggan .*untuk mencegah overmatching. Untuk pola khusus ini, bagaimanapun, ada alternatif yang lebih baik, menggunakan kelas karakter yang dinegasikan.

Pola tersebut A[^Z]*Zjuga menemukan dua kecocokan yang sama dengan A.*?Zpola untuk input di atas ( seperti yang terlihat di ideone.com ). [^Z]adalah apa yang disebut kelas karakter yang dinegasikan : ia cocok dengan apa pun kecuali Z.

Perbedaan utama antara kedua pola tersebut adalah dalam performanya: karena lebih ketat, kelas karakter yang dinegasikan hanya dapat mencocokkan satu cara untuk masukan yang diberikan. Tidak masalah jika Anda menggunakan pengubah serakah atau enggan untuk pola ini. Faktanya, dalam beberapa rasa, Anda dapat melakukan lebih baik lagi dan menggunakan apa yang disebut pembilang posesif, yang tidak mundur sama sekali.

Referensi


Contoh 2: Dari A ke ZZ

Contoh ini harus ilustratif: ini menunjukkan bagaimana pola kelas karakter serakah, enggan, dan dinegasikan cocok secara berbeda dengan input yang sama.

eeAiiZooAuuZZeeeZZfff

Ini adalah kecocokan untuk masukan di atas:

Berikut adalah representasi visual dari apa yang mereka cocokkan:

         ___n
        /   \              n = negated character class
eeAiiZooAuuZZeeeZZfff      r = reluctant
  \_________/r   /         g = greedy
   \____________/g

topik-topik terkait

Ini adalah tautan ke pertanyaan dan jawaban di stackoverflow yang mencakup beberapa topik yang mungkin menarik.

Satu pengulangan serakah bisa melebihi yang lain

poligenelubricants
sumber
1
Maksud saya rubular.com, bukan ideone.com. Kepada orang lain: jangan merevisi postingan ini untuk saya, saya akan melakukannya sendiri pada revisi berikutnya, bersama dengan contoh lainnya. Jangan ragu untuk memberikan umpan balik, saran, dll dalam komentar sehingga saya dapat memasukkannya juga.
poligenelubricants
2
Lihat juga: stackoverflow.com/questions/3145023/…
polygenelubricants
4
Jawaban ini telah ditambahkan ke FAQ Ekspresi Reguler Stack Overflow , di bawah "Quantifiers> More on the difference ..."
aliteralmind
Jawaban ini memang pantas menjadi jawaban yang dipilih !. Terima kasih banyak atas penjelasan rinci Anda.
masky007
Saya menambahkan tag non-serakah . Mengapa, karena pertanyaan itu membutuhkannya, tetapi juga karena pertanyaan itu akan mengarahkan lebih banyak pengguna ke jawaban hebat ini. Dengan kata lain jika Anda memberikan jawaban yang bagus dan jawaban tersebut menggunakan tag yang tidak ada pada pertanyaan tersebut, maka tambahkan tag tersebut karena OP tidak mengetahui bahwa tag tersebut bersuka ria.
Guy Coder
24

Katakanlah Anda memiliki:

<a></a>

<(.*)>akan cocok di a></amana <(.*?)>akan cocok a. Yang terakhir berhenti setelah pertandingan pertama >. Ia memeriksa satu atau 0 kecocokan yang .*diikuti oleh ekspresi berikutnya.

Ekspresi pertama <(.*)>tidak berhenti saat mencocokkan yang pertama >. Ini akan berlanjut sampai pertandingan terakhir >.

Simon
sumber
ini lebih mudah dipahami daripada penjelasan di atas.
Prometheus
Beginilah seharusnya penjelasan.
Mosia Thabo