回答:
貪欲は可能な限り消費します。http://www.regular-expressions.info/repeat.htmlから、HTMLタグをと照合する例を確認できます<.+>
。次のものがあるとします。
<em>Hello World</em>
あなたはと思うかもしれ<.+>
(.
手段以外の改行文字と+
手段1つまたは複数の)のみ一致し<em>
そして</em>
実際に、それは非常に貪欲になり、最初から行くと、<
最後に>
。これは、<em>Hello World</em>
あなたが望んだものの代わりに一致することを意味します。
レイジー(<.+?>
)にすると、これを防ぐことができます。追加することで?
後に+
、我々は繰り返すということを教えできるだけ何回かのように最初ので、>
に出くわす部分で、マッチングを停止します。
正規表現の探索に役立つ優れたツールであるRegExrをダウンロードすることをお勧めします。私は常に使用しています。
<[^>]+>
regex101.com/r/lW0cY6/1
'Greedy'は、可能な限り長い文字列に一致することを意味します。
「レイジー」は、可能な限り短い文字列に一致することを意味します。
たとえば、貪欲はに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
greedy reg式:s.*o
出力:stackoverflo w
レイジーreg式:s.*?o
出力:stacko verflow
re.match('(f)?(.*)', 'food').groups()
してくださいre.match('(f)??(.*)', 'food').groups()
。後者で(f)??
は、可能であっても先頭の「f」に一致しません。したがって、「f」は2番目の「。*」キャプチャグループに一致します。'{n}?'で例を構築できると思います。あまりにも。確かに、これら2つはほとんど使用されていません。
私の知る限り、ほとんどの正規表現エンジンはデフォルトで貪欲です。量指定子の最後に疑問符を追加すると、遅延一致が有効になります。
@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>']
最初に出現する「>」まで一致する代わりに、文字列全体を抽出しました。これは、正規表現のデフォルトの貪欲または「すべてを実行」する動作です。
一方、レイジーマッチングは、「最小限の時間しかかかりません」。これ?
は、パターンの最後にa を追加することで実行できます。
例:
re.findall('<.*?>', text)
#> ['<body>', '</body>']
最初に一致したものだけを取得したい場合は、代わりにsearchメソッドを使用してください。
re.search('<.*?>', text).group()
#> '<body>'
ソース:Python正規表現の例
例によって最もよく示されています。ストリング。192.168.1.1
そして貪欲な正規表現\b.+\b
これは最初のオクテットを与えると思うかもしれませんが、実際には文字列全体と一致します。どうして?。+は貪欲であり、貪欲な一致192.168.1.1
は文字列の最後に到達するまでのすべての文字に一致します。これは重要なビットです!これで、3番目のトークンに一致するものが見つかるまで、一度に1文字ずつバックトラックを開始します(\b
)との。
文字列が4GBのテキストファイルで、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); // ""