如何将此Perl正则表达式转换为Java?

你会如何将这个Perl正则表达式翻译成Java?

/pattern/i 

编译时,它与“PattErn”不匹配,但它失败了

 Pattern p = Pattern.compile("/pattern/i"); Matcher m = p.matcher("PattErn"); System.out.println(m.matches()); // prints "false" 

你会如何将这个Perl正则表达式翻译成Java?

 /pattern/i 

你不能。

这有很多原因。 以下是一些:

  • Java不像Perl那样支持正则表达式的正则表达式语言。 它缺少字形支持(如\X)和完整属性支持(如\p{Sentence_Break=SContinue} ),缺少Unicode命名字符,没有(?|...|...|)分支重置运算符,在Java 7之前没有命名捕获组或逻辑\x{...}转义,没有递归正则表达式等等。我可以写一本关于Java缺少的书:习惯回到与您习惯的相比,使用正则表达式引擎非常原始和笨拙。

  • 另一个更糟糕的问题是因为你有类似\w\b\s ,甚至\p{alpha}\p{lower}类似虚假amis ,与Perl相比,它在Java中表现不同; 在某些情况下,Java版本完全无法使用和错误。 这是因为Perl遵循UTS#18,但在Java 7之前,Java没有。 您必须从Java 7添加UNICODE_CHARACTER_CLASSES标志才能使这些标志不再被破坏。 如果您不能使用Java 7,请立即放弃,因为Java在Java 7之前有许多其他Unicode错误,并且它不值得处理它们的痛苦。

  • Java通过^$和处理换行. ,但Perl希望Unicode换行符为\R 您应该查看UNIX_LINES以了解其中发生的情况。

  • 默认情况下,Java不会应用任何Unicode案例折叠。 确保将UNICODE_CASE标志添加到编译中。 否则你就不会得到各种希腊西格玛相互匹配的东西。

  • 最后,它是不同的,因为最好的 Java只做简单的casefolding,而Perl总是做完整的casefolding。 这意味着你不会得到\xDF来匹配Java中不敏感的“SS”情况以及类似的相关问题。

总之,您可以获得的最接近的是使用标志进行编译

  CASE_INSENSITIVE | UNICODE_CASE | UNICODE_CHARACTER_CLASSES 

这相当于模式字符串中嵌入的"(?iuU)"

请记住,Java中的匹配并不意味着匹配,反过来说。


编辑

这是故事的其余部分……

编译时,它与“PattErn”不匹配,但它失败了

  Pattern p = Pattern.compile("/pattern/i"); Matcher m = p.matcher("PattErn"); System.out.println(m.matches()); // prints "false" 

你不应该在模式周围留下斜线。

你能做的最好的就是翻译

 $line = "I have your PaTTerN right here"; if ($line =~ /pattern/i) { print "matched.\n"; } 

这条路

 import java.util.regex.*; String line    = "I have your PaTTerN right here"; String pattern = "pattern"; Pattern regcomp = Pattern.compile(pattern, CASE_INSENSITIVE                                        | UNICODE_CASE                // comment next line out for legacy Java \b\w\s breakage                                        | UNICODE_CHARACTER_CLASSES                                 ); Matcher regexec = regcomp.matcher(line); if (regexec.find()) {    System.out.println("matched"); } 

在那里,看看有多容易不是吗? 🙂

你失去了Java的另一件事,因为Java实际上并不知道来自其头部漏洞的双向链表的正则表达式,是模式的编译时编译。 我,我总是发现编译时间是编译的最佳时间,但试着告诉Java。 Java使得很难实现非常简单的程序健全度量,这是您在每个程序中始终需要做的事情。 这个设计缺陷是屁股中的皇家痛苦,因为你的程序中途你会在编译期间编译时应该在编译期间捕获的东西例外。 就像coitus interruptus一样令人生气,因为你在完成业务的过程中表现得很好而BANG一切都毁了。

我没有在上面的代码中实现解决这个令人烦恼的烦恼的解决方案,但你可以通过一些静态初始化来伪装它。

Java正则表达式没有分隔符,并使用单独的参数进行修改:

  Pattern p = Pattern.compile("pattern", Pattern.CASE_INSENSITIVE); 

Perl相当于:

 /pattern/i 

在Java中将是:

 Pattern p = Pattern.compile("(?i)pattern"); 

或者干脆做:

 System.out.println("PattErn".matches("(?i)pattern")); 

请注意, "string".matches("pattern")针对整个输入字符串validation模式。 换句话说,以下将返回false:

 "foo pattern bar".matches("pattern")