我多年来一直是一名正则表达式从业者,主要是在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正则表达式实现)。感谢。
答案 0 :(得分:5)
在您的示例中,我认为没有任何理由可以预编译正则表达式。如果我这样做,我只需将delim
,field1
和field2
定义为String
,然后将它们合并。
除此之外,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中的/ /
分隔符实际上只是String
s(如果它们包含变量引用,则为GStrings
)。它们不是真正的正则表达式,但它们不需要双重逃避一切。
如果您想避免转义/
,那么您可以在Groovy 1.8及更高版本中使用dollar-slashy-strings:
def delim = $/[-:/]/$
我认为这不是你的例子所必需的。