如何在Qt-regexp中模拟否定的lookbacking断言

How to emulate a negative lookbehind assertions in Qt regexp?

本文关键字:lookbacking 断言 模拟 Qt-regexp      更新时间:2023-10-16

我正在使用Qt 4.6编写一个程序,我需要从以下表达式中捕获所有出现的非范围文字CCD_ 1,即B1、B3,但不是A1、A3、D1、D3。我尝试过使用QRegExp,但它不支持否定的后备断言,所以我不能排除像A3、D3这样的文字。我的正则表达式(?<!:)([A-Z]{1,4}[1-9]\d{0,3})(?!:)不起作用。我需要你的意见。谢谢

在您的情况下,您可以使用

(?:^|[^:])\b([A-Z]{1,4}[1-9]\d{0,3})\b

第一组匹配开头的空字符串或除冒号以外的任何字符。我还添加了单词边界b,这样模式就不会匹配A4a之类的东西。

通常情况下,写"积极"模式更简单。例如,使用

(…)(:…)

...表示[A-Z]模式以匹配单元格引用,您可以一次性匹配范围和非范围,然后在循环结果时丢弃所有范围。通过检查第二个捕获组是否为空,可以轻松检测匹配是否为范围。

对于需要在不支持查找的引擎上进行查找的解决方案,我只找到了一个替代方案:我称之为"组合暴力",尽管我相信还有一个更技术的名称。这里有一个示例:使用XML正则表达式模式验证代理URL。

但是当您需要查找多个事件时,它不起作用。你可能自己也尝试过这样的东西:

/[^:]b([A-Z]{1,4}[1-9]d{0,3})b[^:]/

(为了更安全,我添加了b。此外,请记住再次转义反斜杠。)

如果你确实尝试过,那么你会注意到问题:第一个匹配是在读取+B1-之后找到的;因此,由于已经读取了-,所以不能匹配下一个小区引用"SUM(A1:A3)+B1-B3+SUM(D1:D3)/COUNT(D1:D3)"0,因为对于[^:]没有合适的字符。

为了重新描述这个问题,上面的正则表达式只能捕获连续单元格引用链中的每一个匹配,例如字符串

(A1+A2+A3+A4+A5+A6)/(B1+B2+B3+B4+B5+B6)
^^^^  ^^^^  ^^^^    ^^^^  ^^^^  ^^^^

只有指示的部分将匹配,也在此处显示。

没有办法在一个正则表达式中绕过这一点。您的替代方案:

  1. 使用非正则表达式方法。

  2. 如果由于某种原因必须使用正则表达式,那么您唯一的希望可能是能够至少使用两个正则表达式(例如,使用第一个在所有单元格引用(如字符串)周围插入空格,这样就没有连续的单元格引用链)。

  3. 或者,在不太可能的情况下,将它们捕获到子匹配中就足够了,即可以通过.cap(1).cap(2)等访问。您可以执行以下操作。


/[^:]b([A-Z]{1,4}[1-9]d{0,3})b[^:](?:(b([A-Z]{1,4}[1-9]d{0,3})b[^:](?:(b([A-Z]{1,4}[1-9]d{0,3})b[^:](?:(b([A-Z]{1,4}[1-9]d{0,3})b[^:](?:(b([A-Z]{1,4}[1-9]d{0,3})b[^:](?:(b([A-Z]{1,4}[1-9]d{0,3})b[^:](?:(b([A-Z]{1,4}[1-9]d{0,3})b[^:]))?))?))?))?))?))?/

好吧,这是不可能阅读的,所以这里有一个可读性更强的版本。假定XY扩展到我们的细胞参考表达b([A-Z]{1,4}[1-9]d{0,3})b。那么,以上与相同

/[^:]XY[^:](?:(XY[^:](?:(XY[^:](?:(XY[^:](?:(XY[^:](?:(XY[^:]))?))?))?))?))?))?/

看到图案了吗?在我们进一步讨论之前,您可以看到这个正则表达式与我们的示例非常匹配。缺点是,只要定义正则表达式,就只能处理连续的单元格引用链。上面的可以处理7,超过这个就坏了。

Qt 5.0中的QRegularExpression支持(固定长度)后备断言。

https://bugreports.qt-project.org/browse/QTBUG-2371于2012年3月22日关闭。Qt 5.0于2012年12月19日发布。