java使用正则表达式匹配多行文本
我正在尝试使用java匹配多行文本。当我将Pattern
类与Pattern.MULTILINE
修饰符一起使用时,我能够匹配,但无法与(?m).
匹配
使用(?m)
和使用String.matches
的相同模式似乎不起作用
我肯定我错过了什么,但不知道是什么。我不太擅长正则表达式
这就是我试过的
String test = "User Comments: This is \t a\ta \n test \n\n message \n";
String pattern1 = "User Comments: (\\W)*(\\S)*";
Pattern p = Pattern.compile(pattern1, Pattern.MULTILINE);
System.out.println(p.matcher(test).find()); //true
String pattern2 = "(?m)User Comments: (\\W)*(\\S)*";
System.out.println(test.matches(pattern2)); //false - why?
# 1 楼答案
str.matches(regex)
behaves like{而
matcher.find()
attempts to find是与模式匹配并返回的输入序列的下一个子序列因此,问题在于正则表达式。尝试以下方法
因此,简而言之,第一个正则表达式中的
(\\W)*(\\S)*
部分匹配一个空字符串,因为*
意味着零次或多次出现,而真正匹配的字符串是User Comments:
,而不是您期望的整个字符串。第二个失败,因为它试图匹配整个字符串,但无法匹配,因为\\W
匹配非单词字符,即[^a-zA-Z0-9_]
,而第一个字符是T
,一个单词字符# 2 楼答案
这与多行标志无关;您看到的是}将成功,而
find()
和matches()
方法之间的差异^如果在目标字符串中的任何位置都能找到匹配项,{matches()
希望正则表达式匹配整个字符串此外,
MULTILINE
并不意味着你认为它是什么。许多人似乎会得出这样的结论:如果目标字符串包含换行符,也就是说,如果它包含多个逻辑行,则必须使用该标志。我在这里看到了一些关于这一点的答案,但事实上,这个标志所做的只是改变锚的行为,^
和$
通常
^
匹配目标字符串的最开头,而$
匹配最结尾(或者在结尾的换行符之前,但我们暂时不讨论这一点)。但是,如果字符串包含换行符,则可以通过设置多行标志来选择^
和$
在任何逻辑行的开始和结束处匹配,而不仅仅是整个字符串的开始和结束处所以,忘掉
MULTILINE
的意思,只记得它做了什么:改变^
和$
锚的行为DOTALL
模式最初被称为“单线模式”(在某些风格中,包括Perl和.NET),它总是引起类似的混淆。幸运的是,在这种情况下,Java开发人员使用了更具描述性的名称,但“多行”模式没有合理的替代方案在Perl中,所有这些疯狂开始了,他们已经承认了自己的错误,并且在Perl6正则表达式中摆脱了“多行”和“单行”模式。再过二十年,也许世界其他地方也会效仿
# 3 楼答案
多行标志告诉正则表达式将模式匹配到每一行,而不是整个字符串。对于您的目的,通配符就足够了
# 4 楼答案
首先,在错误的假设下使用修饰符
Pattern.MULTILINE
或(?m)
告诉Java接受锚^
和$
以在每行的开始和结束处匹配(否则它们只在整个字符串的开始/结束处匹配)Pattern.DOTALL
或(?s)
告诉Java也允许点匹配换行符第二,在您的例子中,正则表达式失败是因为您使用了
matches()
方法,该方法期望正则表达式匹配整个字符串-当然,这不起作用,因为在(\\W)*(\\S)*
匹配之后还有一些字符因此,如果只是查找以
User Comments:
开头的字符串,请使用正则表达式使用
Pattern.DOTALL
选项:ResultString
将在User Comments:
之后包含文本