このように、プログラムで組み立てられた巨大な正規表現がいくつかあります
(A)|(B)|(C)|...
各サブパターンは、そのキャプチャ グループにあります。group(i)
一致した場合、各グループが null 以外の文字列を返すことを直線的にテストせずに、どのグループが一致するかをどのように判断するのですか?
このように、プログラムで組み立てられた巨大な正規表現がいくつかあります
(A)|(B)|(C)|...
各サブパターンは、そのキャプチャ グループにあります。group(i)
一致した場合、各グループが null 以外の文字列を返すことを直線的にテストせずに、どのグループが一致するかをどのように判断するのですか?
次の代わりに、キャプチャしないグループを使用できます。
(A)|(B)|(C)|..。
と置換する
((?: A)|(?: B)|(?: C))
非キャプチャグループ(?:)はグループカウントに含まれませんが、ブランチの結果は外側の()グループにキャプチャされます。
線形探索を回避できるとは思いませんが、のstart(int)
代わりにを使用することで、はるかに効率的にすることができますgroup(int)
。
static int getMatchedGroupIndex(Matcher m)
{
int index = -1;
for (int i = 1, n = m.groupCount(); i <= n; i++)
{
if ( (index = m.start(i)) != -1 )
{
break;
}
}
return index;
}
このように、グループごとにサブストリングを生成する代わりに、int
開始インデックスを表す値を照会するだけです。
さまざまなコメントから、単純な答えは「いいえ」であり、別の正規表現を使用する方が良い考えのようです。このアプローチを改善するには、一般的なパターン プレフィックスを生成するときにそれらを把握するか、独自の正規表現 (またはその他の) パターン マッチング エンジンを使用する必要がある場合があります。しかし、そのすべての作業に取り掛かる前に、これがシステムの重大なボトルネックであることを確認する必要があります。つまり、ベンチマークを実行して、実際の入力データに対してパフォーマンスが許容できるかどうかを確認し、そうでない場合は、実際のボトルネックがどこにあるかをプロファイルで確認します。
正規表現を 3 つに分割します。
String[] regexes = new String[] { "pattern1", "pattern2", "pattern3" };
for(int i = 0; i < regexes.length; i++) {
Pattern pattern = Pattern.compile(regexes[i]);
Matcher matcher = pattern.matcher(inputStr);
if(matcher.matches()) {
//process, optionally break out of loop
}
}
public int getMatchedGroupIndex(Matcher matcher) {
int index = -1;
for(int i = 0; i < matcher.groupCount(); i++) {
if(matcher.group(i) != null && matcher.group(i).trim().length() > 0) {
index = i;
}
}
return index;
}
別の方法は次のとおりです。
for(int i = 0; i < matcher.groupCount(); i++) {
if(matcher.group(i) != null && matcher.group(i).trim().length() > 0) {
//process, optionally break out of loop
}
}