Jawaban:
Serakah akan mengkonsumsi sebanyak mungkin. Dari http://www.regular-expressions.info/repeat.html kita melihat contoh mencoba mencocokkan tag HTML dengan <.+>
. Misalkan Anda memiliki yang berikut:
<em>Hello World</em>
Anda mungkin berpikir bahwa <.+>
( .
berarti karakter bukan baris baru dan +
berarti satu atau lebih ) hanya akan cocok dengan <em>
dan </em>
, ketika pada kenyataannya itu akan sangat serakah, dan pergi dari yang pertama <
ke yang terakhir >
. Ini berarti itu akan cocok dengan <em>Hello World</em>
yang Anda inginkan.
Membuatnya malas ( <.+?>
) akan mencegah hal ini. Dengan menambahkan ?
setelah +
, kami katakan untuk mengulangi sesering mungkin , jadi yang pertama kali ditemukan >
, adalah tempat kami ingin menghentikan pencocokan.
Saya mendorong Anda untuk mengunduh RegExr , alat hebat yang akan membantu Anda menjelajahi Ekspresi Reguler - Saya menggunakannya sepanjang waktu.
<[^>]+>
regex101.com/r/lW0cY6/1
'Serakah' berarti cocok dengan string terpanjang yang mungkin.
'Malas' berarti cocok dengan string yang sesingkat mungkin.
Sebagai contoh, serakah h.+l
pertandingan 'hell'
di 'hello'
tetapi malas h.+?l
pertandingan 'hel'
.
h.+l
Pertandingan serakah 'helol'
di 'helolo'
tapi h.+?l
pertandingan malas 'hel'
.
x?
berarti x
adalah opsional tetapi +?
sintaks yang berbeda. Itu berarti berhenti merawat setelah Anda menemukan sesuatu yang cocok - pencocokan malas.
?
berarti opsional dan +?
berarti malas. Karena itu \+?
berarti +
adalah opsional.
+-------------------+-----------------+------------------------------+
| Greedy quantifier | Lazy quantifier | Description |
+-------------------+-----------------+------------------------------+
| * | *? | Star Quantifier: 0 or more |
| + | +? | Plus Quantifier: 1 or more |
| ? | ?? | Optional Quantifier: 0 or 1 |
| {n} | {n}? | Quantifier: exactly n |
| {n,} | {n,}? | Quantifier: n or more |
| {n,m} | {n,m}? | Quantifier: between n and m |
+-------------------+-----------------+------------------------------+
Tambah sebuah ? ke quantifier untuk membuatnya tidak berkelas yaitu malas.
Contoh:
string uji: stackoverflow
serakah ekspresi reg : s.*o
Output: stackoverflo w
ekspresi reg malas : s.*?o
Output: stacko verflow
re.match('(f)?(.*)', 'food').groups()
dengan re.match('(f)??(.*)', 'food').groups()
. Dalam yang terakhir, (f)??
tidak akan cocok dengan 'f' terkemuka meskipun itu bisa. Oleh karena itu, 'f' akan dicocokkan dengan kelompok tangkapan kedua '. *'. Saya yakin Anda dapat membuat contoh dengan '{n}?' terlalu. Harus diakui keduanya sangat jarang digunakan.
Serakah berarti ekspresi Anda akan cocok dengan kelompok sebanyak mungkin, malas berarti cocok dengan kelompok sekecil mungkin. Untuk string ini:
abcdefghijklmc
dan ungkapan ini:
a.*c
Pertandingan serakah akan cocok dengan seluruh string, dan pertandingan malas akan cocok dengan yang pertama abc
.
Sejauh yang saya tahu, kebanyakan mesin regex serakah secara default. Menambahkan tanda tanya di akhir kuantifier akan memungkinkan kecocokan malas.
Seperti @Andre S disebutkan dalam komentar.
Lihat contoh di bawah ini untuk apa yang serakah dan apa yang malas.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test {
public static void main(String args[]){
String money = "100000000999";
String greedyRegex = "100(0*)";
Pattern pattern = Pattern.compile(greedyRegex);
Matcher matcher = pattern.matcher(money);
while(matcher.find()){
System.out.println("I'm greeedy and I want " + matcher.group() + " dollars. This is the most I can get.");
}
String lazyRegex = "100(0*?)";
pattern = Pattern.compile(lazyRegex);
matcher = pattern.matcher(money);
while(matcher.find()){
System.out.println("I'm too lazy to get so much money, only " + matcher.group() + " dollars is enough for me");
}
}
}
I'm greeedy and I want 100000000 dollars. This is the most I can get.
I'm too lazy to get so much money, only 100 dollars is enough for me
Diambil Dari www.regular-expressions.info
Keserakahan : Kuantitatif serakah pertama kali mencoba mengulangi token sebanyak mungkin, dan secara bertahap menyerah pertandingan sebagai backtracks mesin untuk menemukan kecocokan keseluruhan.
Kemalasan : Pengukur malas pertama-tama mengulangi token sebanyak yang diperlukan, dan secara bertahap memperluas kecocokan saat engine mundur ke belakang melalui regex untuk menemukan kecocokan secara keseluruhan.
Dari ekspresi Reguler
Pengukur standar dalam ekspresi reguler adalah serakah, artinya mereka cocok sebanyak mungkin, hanya memberikan kembali seperlunya untuk mencocokkan sisa regex.
Dengan menggunakan kuantifier malas, ekspresi mencoba kecocokan minimal terlebih dahulu.
Pencocokan serakah. Perilaku default ekspresi reguler adalah menjadi serakah. Itu berarti ia mencoba untuk mengekstrak sebanyak mungkin sampai sesuai dengan suatu pola bahkan ketika bagian yang lebih kecil sudah cukup secara sintaksis.
Contoh:
import re
text = "<body>Regex Greedy Matching Example </body>"
re.findall('<.*>', text)
#> ['<body>Regex Greedy Matching Example </body>']
Alih-alih mencocokkan hingga kemunculan pertama '>', ia mengekstraksi seluruh string. Ini adalah perilaku regex default yang serakah atau 'ambil semuanya.
Pencocokan malas , di sisi lain, 'mengambil sesedikit mungkin'. Ini dapat dilakukan dengan menambahkan a ?
di akhir pola.
Contoh:
re.findall('<.*?>', text)
#> ['<body>', '</body>']
Jika Anda hanya ingin pencocokan pertama yang diambil, gunakan metode pencarian sebagai gantinya.
re.search('<.*?>', text).group()
#> '<body>'
Sumber: Contoh Python Regex
Serakah berarti akan memakan pola Anda sampai tidak ada satupun yang tersisa dan tidak terlihat lagi.
Malas akan berhenti segera setelah akan menemukan pola pertama yang Anda minta.
Salah satu contoh umum yang sering saya temui adalah \s*-\s*?
dari regex([0-9]{2}\s*-\s*?[0-9]{7})
Yang pertama \s*
diklasifikasikan sebagai serakah karena *
dan akan terlihat sebanyak mungkin ruang putih setelah digit dijumpai dan kemudian mencari karakter tanda hubung "-". Sedangkan yang kedua \s*?
adalah malas karena masa kini *?
yang berarti akan terlihat karakter ruang putih pertama dan berhenti di sana.
Terbaik ditunjukkan dengan contoh. Tali. 192.168.1.1
dan regex serakah \b.+\b
Anda mungkin berpikir ini akan memberi Anda oktet 1 tetapi sebenarnya cocok dengan seluruh string. Mengapa? Karena. + Rakus dan serakah cocok dengan setiap karakter 192.168.1.1
hingga mencapai akhir string. Ini bagian yang penting! Sekarang mulai mundur satu karakter pada satu waktu hingga menemukan kecocokan untuk token ke-3 ( \b
).
Jika string file teks 4GB dan 192.168.1.1 sudah di awal Anda bisa dengan mudah melihat bagaimana pengulangan ini akan menyebabkan masalah.
Untuk membuat regex yang tidak serakah (malas) beri tanda tanya setelah pencarian serakah Anda misalnya
*?
??
+?
Apa yang terjadi sekarang adalah token 2 ( +?
) menemukan kecocokan, regex bergerak di sepanjang karakter dan kemudian mencoba token berikutnya ( \b
) daripada token 2 ( +?
). Jadi itu merayap dengan hati-hati.
Jika ada di sana, mereka akan datang dan mengambilnya. Mereka akan mengambil semuanya:
Misalnya, IRS cocok dengan regex ini: .*
$50,000
- IRS akan mengambil semuanya. Mereka serakah .*{4}?
ers
Lihat di sini untuk contoh: regexr.com/4t27f
Di sisi lain, jika saya meminta pengembalian pajak, IRS tiba-tiba menjadi tidak serakah, dan mereka menggunakan penghitung ini:
(.{2}?)([0-9]*)
terhadap ungkapan ini: $50,000
Grup pertama tidak membutuhkan dan hanya cocok $5
- jadi saya mendapatkan $5
pengembalian uang. Sisanya diambil oleh paman Sam untuk dihabiskan dengan sia-sia.
Lihat di sini: Contoh yang tidak tamak .
Menjadi penting jika Anda mencoba mencocokkan bagian-bagian tertentu dari ekspresi. Terkadang Anda tidak ingin mencocokkan segalanya.
cobalah untuk memahami perilaku berikut:
var input = "0014.2";
Regex r1 = new Regex("\\d+.{0,1}\\d+");
Regex r2 = new Regex("\\d*.{0,1}\\d*");
Console.WriteLine(r1.Match(input).Value); // "0014.2"
Console.WriteLine(r2.Match(input).Value); // "0014.2"
input = " 0014.2";
Console.WriteLine(r1.Match(input).Value); // "0014.2"
Console.WriteLine(r2.Match(input).Value); // " 0014"
input = " 0014.2";
Console.WriteLine(r1.Match(input).Value); // "0014.2"
Console.WriteLine(r2.Match(input).Value); // ""