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 可以作为参数传递给 sub)。

问题是,如何在 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

在您的示例中,我根本看不到任何预编译正则表达式的理由。如果我这样做,我只需定义delimfield1field2as Strings,并将它们组合起来。

除此之外,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/

这里需要注意一件事:/ /Groovy 中的分隔符实际上只是Strings(或者GStrings如果它们包含变量引用)。它们不是真正的正则表达式,但它们具有不需要双重转义所有内容的便利。

如果您想避免转义 even /,那么您可以在 Groovy 1.8 及更高版本中使用美元斜线字符串:

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

不过,我认为在您的示例中没有必要这样做。

于 2013-04-03T03:51:30.500 回答