我想创建一个正则表达式,以便将字符串分解为字典中的单词。如果字符串匹配,我可以迭代每个组并进行一些更改。有些词是其他词的前缀。但是,像/(HH|HH12)+/
这样的正则表达式与字符串HH12HH
link不匹配。正则表达式有什么问题?它应该匹配字符串中的第一个HH12
然后HH
吗?
答案 0 :(得分:1)
在字符串HH12HH
中,正则表达式(HH|HH12)+
将以这种方式工作:
HH12HH
^ - both option work, continue
HH12HH
^ - First condition is entierly satisfied, mark it as match
HH12HH
^ - No Match
HH12HH
^ - No Match
当你设置A
标志时,它会将锚点添加到字符串的开头,其余的不会引发匹配。如果您将其删除,则该模式将在开始时与HH
匹配。最后。
在这种情况下,您有三个选择:
/(HH12|HH)/Ag
之前。 See demo 我喜欢的那个。 /(HH(?:12)?)/Ag
。 See second demo $
放在最后,如/(HH|HH12)$/Ag
答案 1 :(得分:1)
您希望匹配Java中的整个字符串,该字符串应仅包含HH12
或HH
个子字符串。通过两个步骤更容易完成:1)检查字符串是否符合要求(此处为matches("(?:HH12|HH)+")
),2)提取所有令牌(此处为HH12|HH
或HH(?:12)?
,因为非锚定交替组中的第一个替代方案“获胜”而其余部分未被考虑)。
String str = "HH12HH";
Pattern p = Pattern.compile("HH12|HH");
List<String> res = new ArrayList<>();
if (str.matches("(?:HH12|HH)+")) { // If the whole string consists of the defined values
Matcher m = p.matcher(str);
while (m.find()) {
res.add(m.group());
}
}
System.out.println(res); // => [HH12, HH]
请参阅Java demo
另一种方法是使用正则表达式来检查字符串是否满足开头的前瞻要求,然后将匹配连续令牌与\G
运算符:
String str = "HH12HH";
Pattern p = Pattern.compile("(\\G(?!^)|^(?=(?:HH12|HH)+$))(?:HH12|HH)");
List<String> res = new ArrayList<>();
Matcher m = p.matcher(str);
while (m.find()) {
res.add(m.group());
}
System.out.println(res);
详细:
(\\G(?!^)|^(?=(?:HH12|HH)+$))
- 上一次成功匹配(\\G(?!^)
)或(|
)字符串开始(^
),后面跟着1+个{ {1}}或HH12
(HH
)直至字符串末尾((?:HH12|HH)+
)$
- (?:HH12|HH)
或HH12
。答案 2 :(得分:0)
您遇到的问题与正则表达式引擎决定匹配的方式完全相关。
正如我解释here,有一些正则表达式选择最长的替换...但你没有使用它。 Java的正则表达式引擎是另一种类型:使用第一个匹配的交替。
你的正则表达式与这段代码非常相似:
if(bool1){
// This is where `HH` matches
} else if (bool1 && bool2){
// This is where `HH12` would match, but this code will never execute
}
解决此问题的最佳方法是反向排序,以便{/ 1}} HH12
之前发生。
然后,您可以匹配更改:
HH
匹配是非常明显的,因为你可以得到每场比赛的结果。
(您也可以将每个单词放在自己的捕获组中,但这有点难以使用。)