最善の策は、文字列の先頭と末尾を完全に一致させようとすることをスキップすることです。メソッドを使用する場合はそれを行う必要がありますが、matches()
メソッドを使用する場合はそうではありませんfind()
。それはおそらくあなたが代わりに望むものです。
Pattern p = Pattern.compile("<b>\\s*([^<]*)\\s*<\\/b>");
Matcher m = p.matcher("some <b>text</b>");
m.find();
とを使用start()
しend()
て、一致を含むソース文字列内のインデックスを見つけることができます。一致内のキャプチャの内容(つまり、太字のタグ内のテキスト)group()
を見つけるために使用できます。()
私の経験では、正規表現を使用してHTMLを処理することは非常に脆弱であり、最も些細な場合にのみうまく機能します。代わりに本格的なXMLパーサーを使用する方が幸運かもしれませんが、これがこれらの些細なケースの1つである場合は、それを使用してください。
元の回答:これが私の元の回答.*
で、試合開始時のパフォーマンスが非常に悪い理由を共有しています。
フロントで使用する場合の問題.*
は、試合で多くのバックトラックが発生することです。たとえば、次のことを考慮してください。
Pattern p = Pattern.compile("(.*)ab(.*)");
Matcher m = p.matcher("aaabaaa");
m.matches();
試合は次のように進行します。
- マッチャーは、文字列全体「aaabaaa」を最初の文字列に吸い込もうとします
.*
が、その後、照合を試みてa
失敗します。
- マッチャーはバックアップして「aaabaa」と一致し、次に一致
a
を試みて成功しますが、一致b
を試みて失敗します。
- マッチャーはバックアップして「aaaba」と一致し、次に一致
a
を試みて成功しますが、一致b
を試みて失敗します。
- マッチャーはバックアップして「aaab」と一致し、次に一致
a
して成功しようb
としますが、一致しようとして失敗します。
- マッチャーはバックアップして「aaa」と一致し、次に一致しようとして
a
失敗します。
- マッチャーはバックアップして「aa」を照合し、次に照合
a
して成功し、試行b
して成功し、「aaa」を最後に照合し.*
ます。成功。
可能な限り、パターン一致の開始に向けて本当に広い一致を避けたいと考えています。あなたの実際の問題を知らなければ、より良い何かを提案することは非常に難しいでしょう。
更新: Anirudhaは(.*?)ab(.*)
、バックトラックを回避するための可能な修正として使用することを提案しています。これにより、バックトラックがある程度短絡しますが、試行ごとに次の一致を適用しようとするという犠牲が伴います。では、次のことを考慮してください。
Pattern p = Pattern.compile("(.*?)ab(.*)");
Matcher m = p.matcher("aaabaaa");
m.matches();
これは次のように進行します。
- マッチャーは、最初の「」に何も一致させようとせず、一致させよ
.*?
うとしてa
成功しますが、一致しませんb
。
- マッチャーは、最初の文字「a」を最初の文字に一致させようとし、
.*?
一致させようとしてa
成功しますが、一致しませんb
。
- マッチャーは、最初の2文字「aa」を最初の文字に一致さ
.*?
せようとし、一致a
させて成功させ、一致さb
せて成功させ、残りを.*
「aaa」に丸呑みします。成功。
今回はバックトラックはありませんが、内の前進ごとに、より複雑なマッチングプロセスがあります.*?
。これは、特定の試合のパフォーマンスの向上、または試合の進行の反復がたまたま遅い場合の損失である可能性があります。
これにより、試合の進行方法も変わります。試合は貪欲で、より保守的.*
な場所で可能な限り試合を試みます。.*?
たとえば、文字列「aaabaaabaaa」。
最初のパターンは、(.*)ab(.*)
「aaabaa」を最初のキャプチャに一致させ、「aaa」を2番目のキャプチャに一致させます。
2番目のパターンは、(.*?)ab(.*)
「aa」を最初のキャプチャに一致させ、「aaabaaa」を2番目のキャプチャに一致させます。