6

私は何年もの間、主にperlで正規表現の実践者であり、次のような便利なことを行うことができます:

my $delim  = qr#[-\:/]#;                       # basic enough
my $field1 = qr/(\d{8})/;                      # basic enough
my $field2 = qr/(?:one|two|three)(\d{8,10})/;  # basic enough
...
my $re = qr/$field1${delim}$field2/;      # beautiful magicks
while (<>) { 
  /$re/ and print "$1\n";
}

重要なのは、それらをプリコンパイルできるということではなく、ある正規表現を別の正規表現内で変数として使用して、実際に読み取り可能なより大きな複合正規表現を構築できるということです。個々の部分は単純なテスト データでテスト可能であり、複合は動的にすることができます (たとえば、$delim を引数としてサブルーチンに渡すことができます)。

問題は、Pattern/Matcher アプローチが主流である Java でこれにどのようにアプローチするかです。

ここに私の刺し傷があります:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

Pattern delim  = Pattern.compile("[-\:/]");
Pattern field1 = Pattern.compile("(\d{8})");
Pattern field2 = Pattern.compile("(?:one|two|three)(\d{8,10})");
Pattern re_pat = Pattern.complle(
  field1.pattern() + delim.pattern() + field2.pattern();
)
...
Matcher re = re_pat.matcher(input);

これは信頼できますか (落とし穴はありますか?)、それ以外の場合は Java の同等品として最適ですか? また、Groovy との関係で自由に答えてください。これは、このコードの最終的な目的地であるためです (しかし、Groovy は、基盤となる Java 正規表現の実装に多かれ少なかれ依存しているようです)。ありがとう。

4

1 に答える 1

7

あなたの例では、正規表現をプリコンパイルする理由はまったくありません。私がそうしていたら、 、 、 を s として定義delimし、field1それらfield2String結合するだけです。

それに加えて、Groovy は Java の冗長な正規表現の醜さをうまく隠しています。例は次のようになります。

def delim  = /[-:\/]/
def field1 = /(\d{8})/
def field2 = /(?:one|two|three)(\d{8,10})/
def re_pat = /$field1${delim}$field2/

// optionally import Matcher and explicitly declare re
def re = input =~ re_pat

Patternすでにコンパイルされている正規表現をキャッシュするため、事前に正規表現をコンパイルすることを心配する必要はありません(私の記憶が正しければ)。パターンをプリコンパイルする場合は、次を使用します。

def re_pat = ~/$field1${delim}$field2/

ここで 1 つ注意してください/ /。Groovy の区切り文字は、実際には単なるStrings です (GStrings変数参照が含まれている場合)。これらは実際には正規表現ではありませんが、すべてを二重にエスケープする必要がないという便利さがあります。

でさえもエスケープしたくない場合は、Groovy 1.8 以降でDollar-Slashy-Strings/を使用できます。

def delim = $/[-:/]/$

ただし、あなたの例ではそれは必要ないと思います。

于 2013-04-03T03:51:30.500 に答える