具有负前瞻性的正则表达式,跨越多行

时间:2013-08-13 18:49:52

标签: regex

我在为当前的测试用例获取正确的正则表达式时遇到了麻烦。

示例测试用例:

#include <stdio.h>
#include <stdlib.h>
#include <foo_file.h>

int myint = atoi(foostring1);

float myfloat = atof(foostring2);

int myint2 = atoi(foostring3);

用例:

  1. 字符串包含atof 和
  2. string不包含字符串stdlib.h
  3. 小组无所谓。我只是想知道字符串是否存在。
  4. 使用正则表达式

    (?=^#include <stdlib.h>).*atof
    

    我可以找到该文件是否包含stdlib header和atof。效果很好。然而 我似乎无法得到负面的期待正则表达式

    (?!(?=.*^#include <stdlib.h>)).*(atoi)
    

    我已经尝试了上述正则表达式行的多个小时的不同迭代但是 不能让它工作。

    假设我正在使用的IDE的正则表达式引擎允许在新/行之间进行匹配 返回字符,并允许我选择我想要的正则表达式解析器/引擎 使用(但我通常使用perl)

1 个答案:

答案 0 :(得分:1)

问题是你的匹配可以从字符串中的任何地方开始。特别是,您在<{em> #include stdlib.h之后找到匹配。然后前瞻没有找到任何进一步的stdlib.h并且匹配成功。无论多线模式如何,许多正则表达式都会提供\A来匹配字符串的开头(并且仅在那里)。因此,要强制前瞻查看整个字符串,请执行以下操作:

\A(?!.*^#include <stdlib[.]h>).*(atoi)

请注意,您无需在内部嵌套另一个前瞻。

另请注意,即使#include atoi之后的,这也会失败。如果不希望这样,基本上有两种解决方案:

如果你可以选择.NET的正则表达式风格,你可以把它变成一个后视:

(?<!^#include <stdlib[.]h>.*)atoi

其他口味不允许这样,因为它们需要外观具有固定的宽度。

在这些情况下,您必须检查字符串开头和atoi之间的每个位置,它不会标记include的开头:

\A(?:(?!^#include <stdlib[.]h>).)*(atoi)

因此(?:...)组将一个任意字符与该特定位置的前瞻组合在一起,整个事情都会重复。