Відповіді:
Жадібні будуть споживати якомога більше. З http://www.regular-expressions.info/repeat.html ми бачимо приклад спроби співставити теги HTML <.+>
. Припустимо, у вас є наступне:
<em>Hello World</em>
Ви можете подумати, що <.+>
( .
означає, що будь-який символ, що не є новим рядком і +
означає один або кілька ), відповідатиме лише тому <em>
і тому </em>
, коли насправді воно буде дуже жадібним, і піде від першого <
до останнього >
. Це означає, що він буде відповідати <em>Hello World</em>
замість того, що ви хотіли.
Зробити це лінивим ( <.+?>
) запобіжить цьому. Додавши ?
після +
, ми говоримо, щоб це повторилося якомога менше разів , тому перше, >
що трапляється, - це те, де ми хочемо зупинити відповідність.
Я б закликав вас завантажити RegExr , чудовий інструмент, який допоможе вам вивчити регулярні вирази - я використовую його постійно.
<[^>]+>
вирішити
"Жадібний" означає відповідність найдовшої струни.
"Ледачий" означає збіг найкоротшого можливого рядка.
Наприклад, жадібні h.+l
сірники 'hell'
в, 'hello'
але ліниві h.+?l
сірники 'hel'
.
h.+l
сірники 'helol'
в, 'helolo'
але ліниві h.+?l
сірники 'hel'
.
x?
Означає x
необов'язково, але +?
це інший синтаксис. Це означає, що перестаньте доглядати, коли ви знайдете щось, що відповідає - ліниве відповідність.
?
означає необов’язковий та +?
означає лінивий. Тому \+?
засоби +
необов’язкові.
+-------------------+-----------------+------------------------------+
| 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 |
+-------------------+-----------------+------------------------------+
Додати? до кількісного показника, щоб зробити його нечестивим, тобто лінивим.
Приклад:
Тест рядок: StackOverflow
жадібні вираз рег : s.*o
вихід: stackoverflo ш
ледачим виразом рег : s.*?o
вихід: stacko verflow
re.match('(f)?(.*)', 'food').groups()
з re.match('(f)??(.*)', 'food').groups()
. В останньому, (f)??
він не буде відповідати провідному 'f', хоча це міг. Отже, 'f' буде відповідати другій '. *' Групі захоплення. Я впевнений, що ви можете сконструювати приклад із '{n}?' теж. Справді, ці два дуже рідко використовуються.
Жадібний означає, що ваш вираз буде відповідати якомога більшій групі, лінивий означає, що він відповідає найменшій можливій групі. Для цього рядка:
abcdefghijklmc
і цей вираз:
a.*c
Жадібний сірник відповідатиме всій струні, а лінивий - лише перший abc
.
Наскільки мені відомо, більшість двигунів-регексів за замовчуванням жадібні. Додайте знак запитання в кінці кількісного показника, це дозволить лінивому збігу.
Як в коментарі згадував @Andre S
Зверніться до прикладу нижче щодо того, що жадібно, а що ліниво.
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
Взято з www.regular-expressions.info
Жадібність : Жадібні квантори спочатку намагаються повторити маркер якомога більше разів і поступово відмовляються від матчів, як відкликає двигун, щоб знайти загальний збіг.
Лінь : Ледачий квантор спочатку повторює маркер в кілька разів, ніж потрібно, і поступово розширює матч, коли двигун відхиляється через регулярний вираз, щоб знайти загальну відповідність.
Стандартні квантори в регулярних виразах жадібні, тобто вони відповідають максимальній кількості, лише віддаючи за необхідністю, щоб відповідати решті регулярних виразів.
Використовуючи лінивий квантор, вираз спочатку намагається мінімально відповідати.
Жадібна відповідність. Типова поведінка регулярних виразів має бути жадібною. Це означає, що вона намагається витягти якомога більше, поки вона не відповідає шаблону, навіть коли менша частина була б синтаксично достатньою.
Приклад:
import re
text = "<body>Regex Greedy Matching Example </body>"
re.findall('<.*>', text)
#> ['<body>Regex Greedy Matching Example </body>']
Замість того, щоб відповідати до першого появи ">", він витягнув весь рядок. Це жадібна за замовчуванням або поведінка «регулярно приймати все».
Ледача відповідністьЗ іншого боку, "займає якнайменше". Це можна досягти, додавши в ?
кінці шаблону а.
Приклад:
re.findall('<.*?>', text)
#> ['<body>', '</body>']
Якщо ви хочете отримати лише першу відповідність, замість цього скористайтеся методом пошуку.
re.search('<.*?>', text).group()
#> '<body>'
Джерело: Приклади Python Regex
Жадібний означає, що він буде споживати ваш візерунок, поки не залишиться жоден з них і він не може виглядати далі.
Ледачий припиниться, як тільки зустріне перший шаблон, про який ви просили.
Один поширений приклад, з яким я часто стикаюся, - це \s*-\s*?
це регулярний вираз([0-9]{2}\s*-\s*?[0-9]{7})
Перший \s*
класифікується як жадібний через те, що *
після набору цифр буде виглядати якомога більше пробілів, а потім шукати штриховий символ "-". Де як другий \s*?
лінивий через сьогодення, *?
що означає, що він буде виглядати першим символом білого простору і зупиниться прямо там.
Найкраще показано на прикладі. Рядок. 192.168.1.1
і жадібний вираз \b.+\b
Ви можете подумати, що це дасть вам 1-й октет, але насправді відповідає цілому рядку. Чому? Оскільки. + Є жадібним, а жадна відповідність відповідає кожному символу, 192.168.1.1
поки не досягне кінця рядка. Це важливий біт! Тепер він починає відслідковувати один символ за часом, поки не знайде збіг для 3-го маркера ( \b
).
Якщо на початку був рядковий текстовий файл розміром 4 Гб і 192.168.1.1, ви могли легко зрозуміти, як ця зворотня перевірка спричинить проблему.
Щоб зробити регулярний вираз не жадібний (лінивий), після вашого жадібного пошуку поставте знак питання, наприклад
*?
??
+?
Що відбувається зараз - маркер 2 ( +?
) знаходить відповідність, регулярний вираз рухається по символу, а потім намагається наступний жетон ( \b
), а не маркер 2 ( +?
). Так воно обережно повзає.
Якщо він там, вони прийдуть і візьмуть його. Вони візьмуть усе:
Наприклад, IRS відповідає цій графіці: .*
$50,000
- IRS візьме все це. Цей жадібний .*{4}?
ERS
Дивіться тут приклад: regexr.com/4t27f
З іншого боку, якщо я попрошу повернення податку, раптом IRS стає не жадібним, і вони використовують цей кількісний показник:
(.{2}?)([0-9]*)
проти цього виразу: $50,000
Перша група не потребує і відповідає лише $5
тому я отримую$5
відшкодування. Решту бере дядько Сем на марнотратні витрати.
Дивіться тут: Приклад, що не є жадібним .
Це стає важливим, якщо ви намагаєтеся відповідати певним частинам виразу. Іноді не хочеться відповідати всім.
спробуйте зрозуміти таку поведінку:
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); // ""