最好的办法是完全跳过匹配字符串的开头和结尾的尝试。如果您使用该方法,则必须这样做,matches()但如果您使用该方法,则不必这样做find()。这可能就是你想要的。
Pattern p = Pattern.compile("<b>\\s*([^<]*)\\s*<\\/b>");
Matcher m = p.matcher("some <b>text</b>");
m.find();
您可以使用start()andend()来查找包含匹配项的源字符串中的索引。您可以使用在匹配项内group()查找()捕获的内容(即粗体标记内的文本。
以我的经验,使用正则表达式来处理 HTML 是非常脆弱的,并且只在最微不足道的情况下工作得很好。改用成熟的 XML 解析器可能会更好,但如果这是其中一种微不足道的情况,那就试试吧。
原始答案:这是我的原始答案,分享为什么 a.*在比赛开始时表现如此糟糕。
在前面使用的问题.*是它会在你的比赛中导致很多回溯。例如,考虑以下情况:
Pattern p = Pattern.compile("(.*)ab(.*)");
Matcher m = p.matcher("aaabaaa");
m.matches();
比赛将这样进行:
- 匹配器将尝试将整个字符串“aaabaaa”吸进第一个
.*,但随后尝试匹配a并失败。
- 匹配器将备份并匹配“aaabaa”,然后尝试匹配
a并成功,但尝试匹配b并失败。
- 匹配器将备份并匹配“aaaba”,然后尝试匹配
a并成功,但尝试匹配b并失败。
- 匹配器将备份并匹配“aaab”,然后尝试匹配
a并成功,但尝试匹配b并失败。
- 匹配器将备份并匹配“aaa”,然后尝试匹配
a并失败。
- 匹配器将备份并匹配“aa”,然后尝试匹配
a并成功,尝试b并成功,然后将“aaa”匹配到 final .*。成功。
您希望尽可能避免在模式匹配开始时进行非常广泛的匹配。在不了解您的实际问题的情况下,很难提出更好的建议。
更新: Anirudha 建议使用(.*?)ab(.*)作为一种可能的解决方法来避免回溯。这会在一定程度上缩短回溯,但代价是每次尝试都尝试应用下一个匹配。所以现在,考虑以下几点:
Pattern p = Pattern.compile("(.*?)ab(.*)");
Matcher m = p.matcher("aaabaaa");
m.matches();
它将像这样进行:
- 匹配器将尝试不匹配任何内容,“”,进入第一个
.*?,尝试匹配a并成功,但未能匹配b。
- 匹配器将尝试将第一个字母“a”匹配到第一个
.*?,尝试匹配a并成功,但匹配失败b。
- 匹配器将尝试将前两个字母 "aa" 匹配到第一个
.*?,尝试匹配a并成功,尝试匹配b并成功,然后将其余字母吞入.*"aaa"。成功。
这次没有任何回溯,但对于 内的每一次前进,我们仍然有一个更复杂的匹配过程.*?。这可能是特定匹配的性能提升,或者如果向前迭代匹配的速度较慢,则可能会造成损失。
这也改变了比赛的进行方式。匹配是贪婪的,并试图在更保守.*的地方尽可能多地匹配。.*?
例如,字符串“aaabaaabaaa”。
第一个模式(.*)ab(.*)将匹配“aaabaa”到第一个捕获和“aaa”到第二个。
第二个模式(.*?)ab(.*)将匹配“aa”到第一个捕获和“aaabaaa”到第二个。