我多年来一直是正则表达式从业者,主要是在 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 中如何解决这个问题,其中 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);
这是可靠的(有什么问题吗?),否则是最好的 Java 等价物吗?也可以相对于 Groovy 回答这个问题,因为这是我编写这段代码的最终目标(但似乎 Groovy 或多或少依赖于底层的 Java 正则表达式实现)。谢谢。
最佳答案
在您的示例中,我根本看不到任何预编译正则表达式的理由。如果我这样做,我只需定义 delim
, field1
, 和 field2
如 String
s,并将它们组合起来。
除此之外,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
,如果它们包含变量引用)。它们并不是真正的正则表达式,但它们具有不需要对所有内容进行双重转义的便利。如果你想避免逃避甚至
/
,那么您可以使用 dollar-slashy-strings在 Groovy 1.8 及更新版本中:def delim = $/[-:/]/$
不过,我认为在您的示例中没有必要这样做。
关于regex - 组合多个正则表达式模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15778173/