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

时间:2011-09-02 19:55:23

标签: java regex perl

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

/pattern/i

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

Pattern p = Pattern.compile("/pattern/i");
Matcher m = p.matcher("PattErn");

System.out.println(m.matches()); // prints "false"

3 个答案:

答案 0 :(得分:13)

  

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

/pattern/i

你不能。

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

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

  • 另一个更糟糕的问题是因为你有像\w以及\b\s,甚至\p{alpha}一样的 faux amis \p{lower},与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一切都毁了。

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

答案 1 :(得分:1)

Perl相当于:

/pattern/i
Java中的

将是:

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

或者干脆做:

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

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

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

答案 2 :(得分:1)

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

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