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

Jam*_*sev 4 java regex perl

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

/pattern/i
Run Code Online (Sandbox Code Playgroud)

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

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

System.out.println(m.matches()); // prints "false"
Run Code Online (Sandbox Code Playgroud)

tch*_*ist 13

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

/pattern/i
Run Code Online (Sandbox Code Playgroud)

你不能.

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

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

  • 另一种更糟糕的问题是,因为你有外形相似的人造阿美族\w和和\b\s,甚至\p{alpha}\p{lower},其行为不同的Java用Perl比较; 在某些情况下,Java版本完全无法使用并且有错误.那是因为Perl遵循UTS#18但在Java 7之前,Java没有.您必须添加UNICODE_CHARACTER_CLASSESJava 7中的标志才能使这些标志不再被破坏.如果您不能使用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
Run Code Online (Sandbox Code Playgroud)

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

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


编辑

这是故事的其余部分......

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

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

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

你能做的最好的就是翻译

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

这条路

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

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

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

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