正则表达式将字符串分解为字典中的单词

时间:2016-11-14 21:06:09

标签: java regex

我想创建一个正则表达式,以便将字符串分解为字典中的单词。如果字符串匹配,我可以迭代每个组并进行一些更改。有些词是其他词的前缀。但是,像/(HH|HH12)+/这样的正则表达式与字符串HH12HH link不匹配。正则表达式有什么问题?它应该匹配字符串中的第一个HH12然后HH吗?

3 个答案:

答案 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)?)/AgSee second demo
  • $放在最后,如/(HH|HH12)$/Ag

答案 1 :(得分:1)

您希望匹配Java中的整个字符串,该字符串应仅包含HH12HH个子字符串。通过两个步骤更容易完成:1)检查字符串是否符合要求(此处为matches("(?:HH12|HH)+")),2)提取所有令牌(此处为HH12|HHHH(?: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);

请参阅another Java demo

详细

  • (\\G(?!^)|^(?=(?:HH12|HH)+$)) - 上一次成功匹配(\\G(?!^))或(|)字符串开始(^),后面跟着1+个{ {1}}或HH12HH)直至字符串末尾((?: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

匹配是非常明显的,因为你可以得到每场比赛的结果。

(您也可以将每个单词放在自己的捕获组中,但这有点难以使用。)