为何(ending)?$正则未正确匹配?如何实现仅追加一次指定内容?
问题分析与解决方案
为什么(ending)?$无法实现需求
你的问题不是因为()?是惰性匹配,而是这个正则的逻辑存在漏洞:
(ending)?$表示可选匹配结尾的"ending",然后匹配字符串结尾。这意味着无论字符串是否以"ending"结尾,这个正则都能找到匹配项:- 当字符串不以"ending"结尾时,匹配结尾的空位置(
?取0次匹配),替换后追加"ending",这符合预期。 - 当字符串已经以"ending"结尾时,正则既可以匹配结尾的"ending"(
?取1次匹配),也可以匹配结尾的空位置(?取0次匹配)。而QString的replace会替换所有非重叠匹配项,空位置的匹配会被替换成"ending",导致重复追加。
- 当字符串不以"ending"结尾时,匹配结尾的空位置(
另外你提到的string(ending)?$的例子,本质是正则必须先匹配"string",再可选匹配"ending",初始字符串"Init string"中没有后续的"ending",所以?取0次匹配,整个匹配内容是"string",替换后变成"ending",这是正则的正常匹配逻辑,和惰性无关。
实现需求的正确方案
要实现"重复应用模式仅追加一次"的效果,需要确保只有当字符串不以"ending"结尾时,才在结尾追加内容。可以使用负向后顾断言来实现,Qt 5.14的QRegularExpression基于PCRE,支持固定长度的后顾断言("ending"长度固定,符合要求)。
代码示例
QString pattern("(?<!ending)$"); QString after("ending"); // 第一次执行:初始字符串不以ending结尾,匹配结尾空位置,追加ending str.replace(QRegularExpression(pattern), after); // 第二次执行:字符串已以ending结尾,(?<!ending)$不匹配,无修改 str.replace(QRegularExpression(pattern), after);
正则解释
(?<!ending):负向后顾断言,检查当前位置(字符串结尾)的前面是否不是"ending"。如果前面是"ending",则断言失败,整个正则不匹配。$:匹配字符串结尾的空位置。
这样,只有当字符串不以"ending"结尾时,正则才会匹配结尾的空位置,替换后追加"ending";当字符串已经以"ending"结尾时,断言失败,正则不匹配,不会执行替换,自然也就不会重复追加。
内容的提问来源于stack exchange,提问作者Dmitry Kuzminov
相关产品推荐
相关产品推荐

