如何在Qt regexp中模拟负面的lookbehind断言?

时间:2012-07-10 05:16:39

标签: c++ regex qt

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

3 个答案:

答案 0 :(得分:2)

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

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

第一组匹配开头的空字符串或除冒号之外的任何字符。我还添加了字边界 \b,以便该模式与A4a之类的内容不匹配。

通常,编写“正面”模式更简单。例如,使用

(...)(:...)?

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

答案 1 :(得分:0)

对于需要在不支持外观的引擎上使用外观的解决方案,我发现只有一种选择:“我称之为”组合式暴力破解“,但我确信这是一个更具技术性的名称。这里有一个例子:Validate proxy URL using XML regex pattern

当你需要找到多个事件时它不起作用。你可能自己尝试过这样的事情:

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

(我添加了\b以更安全。另外,请记住再次逃避反斜杠。)

如果您尝试了此操作,那么您会注意到problem:在阅读+B1-后找到第一个匹配项;因此,由于-已被阅读,因此无法匹配下一个单元格引用B3,因为[^:]没有合适的字符。

要重新描述该问题,上述正则表达式只能捕获连续的单元格引用链中的所有其他匹配项,例如对于字符串,

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

...只有指定的部分匹配,同时显示here

没有办法在一个正则表达式中解决这个问题。你的选择:

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

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

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


  4. /[^:]\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[^:]))?))?))?))?))?))?/
    

    看模式?在我们进一步讨论之前,您可以看到this regex matches our example perfectly。缺点是只要定义正则表达式,就只能处理一系列连续的单元格引用。以上可以处理7,除此之外breaks

答案 2 :(得分:0)

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

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