结合多种正则表达式模式

Joe*_*ger 4 regex groovy

我多年来一直是正则表达式的从业者,主要是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";
}
Run Code Online (Sandbox Code Playgroud)

关键不是您可以对其进行预编译,而是可以在另一个内部使用一个正则表达式作为变量来构建一个更大的,实际可读的复合正则表达式。各个片段都是可测试的,带有简单的测试数据,并且合成的片段可以是动态的(例如,$ delim可以作为参数传递给子对象)。

问题是,在Java中,Pattern / Matcher方法是一天的主要方式,如何解决这一问题。

这是我的刺:

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);
Run Code Online (Sandbox Code Playgroud)

这是可靠的(是否有陷阱吗?),或者是否是等效的最佳Java?相对于Groovy,也可以随意回答这个问题,因为这是我编写此代码的最终目的(但Groovy似乎或多或少地依赖于底层Java regex实现)。谢谢。

Ove*_*ous 6

在您的示例中,我完全没有理由预编译正则表达式。如果我这样做,我只是定义delimfield1以及field2StringS,并结合他们。

除此之外,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
Run Code Online (Sandbox Code Playgroud)

您不必担心事先编译正则表达式,因为Pattern它会缓存已编译的正则表达式(如果我没记错的话)。如果要预编译模式,请使用以下命令:

def re_pat = ~/$field1${delim}$field2/
Run Code Online (Sandbox Code Playgroud)

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

如果要避免偶数转义/,则可以在Groovy 1.8及更高版本中使用$ -slashy-strings

def delim = $/[-:/]/$
Run Code Online (Sandbox Code Playgroud)

不过,我认为在您的示例中这不是必需的。