我有以下正则表达式,它匹配开头的任何字符,以括号"Hi (Stackoverflow)"
中的文本结尾。
当我输入要匹配的文本时,程序就会继续运行。
String pattern = "^[a-zA-Z]+([\\s]*[\\w]*)*\\([\\w]+\\)"
String text = "Asdadasdasd sadsdsad sdasd (s)"
String text2 = "Asdadasdasd sadsdsad sdasd (s) sdsd"
System.out.println(text.matches(pattern)) - it works
System.out.println(text2.matches(pattern)) - never ending story
有什么问题?
答案 0 :(得分:0)
private static final Pattern pattern = Pattern.compile("[a-zA-Z]+([\\s]*[\\w]*)*\\([\\w]+\\)");
public static void main(String[] args) {
String text = "Asdadasdasd sadsdsad sdasd (s)";
String text2 = "Asdadasdasd sadsdsad sdasd (s) sdsd (k) ssdd";
match(text);
match(text2);
}
private static void match(String text) {
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
System.out.println(matcher.group(0));
}
}
,输出为:
Asdadasdasd sadsdsad sdasd (s)
Asdadasdasd sadsdsad sdasd (s)
sdsd (k)
答案 1 :(得分:0)
由于你的正则表达式中的*
,第二个需要很长时间(或者至少需要很长时间,具体取决于实现)。
你的正则表达式开始试图像这样匹配:
[a-zA-Z]+ \s* \w* \s* \w* \s* \w* \( \w+ \) [unmatched]
Asdadasdasd sadsdsad sdasd X ( s ) sdsd
此时你可能会说它"好吧,不匹配,我们已经完成了#34;。
但这不是它的作用。
相反,它会backtrack试图找到一个可行的匹配(因为在这种情况下计算机找出回溯将是浪费时间并不是那么容易)。
以前匹配第二个\w*
到sdasd
的位置,它现在会尝试少一个字符,即sdas
,然后它会添加另一个匹配的\s*\w*
\s*
为{0}个字符,d
为\w*
。
[a-zA-Z]+ \s* \w* \s* \w* \s* \w* \s* \w* \( \w+ \) [unmatched]
Asdadasdasd sadsdsad sdas X d X ( s ) sdsd
这也不会起作用,所以它会尝试sda
然后再sd
,它不会工作并导致它将其进一步分解为{{1} },sda
和s
。
d
依此类推,直到每个[a-zA-Z]+ \s* \w* \s* \w* \s* \w* \s* \w* \( \w+ \) [unmatched]
Asdadasdasd sadsdsad sda X sd X ( s ) sdsd
[a-zA-Z]+ \s* \w* \s* \w* \s* \w* \s* \w* \s* \w* \( \w+ \) [unmatched]
Asdadasdasd sadsdsad sda X s X d X ( s ) sdsd
只匹配一个字符。
PS:以上并不一定完全它的作用,它更倾向于对发生的事情有一个基本的了解。
PPS:为简洁起见,使用\w
代替\
。
有几种方法可以解决它。
要求变化最小的那个可能是使用\\
代替(\\s*\\w*)*+
制作*+
possessive,这会阻止它完全回溯(这是排队的)我们想要的东西)。
*
使用^[a-zA-Z]+(\\s*\\w*)*+\\(\\w+\\)
而不是\\s+
也会有用,虽然这会导致一些略有不同的行为(特别是0-9不能再出现在第一个空格之前,这可能是通过在括号前添加\\s*
来修复。
这可以修复它,因为我们无法再为\\w*
匹配0个字符,这会阻止我们在回溯时会做很多工作。
\\s
我也建议在任何一种情况下都从 ^[a-zA-Z]+(\\s+\\w*)*\\(\\w+\\)
OR ^[a-zA-Z]+\\w*(\\s+\\w*)*\\(\\w+\\)
删除+
,因为[a-zA-Z]
已经涵盖了这一点(因此不会改变正则表达式匹配)和(在我看来)使正则表达式的期望行为在看时更清晰。
PS: \\w*
相当于[\\s]*
。