最好的办法是完全跳过匹配字符串的开头和结尾的尝试。如果您使用该方法,则必须这样做,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”到第二个。