【问题标题】:Write c++ regular expression to match a #include preprocessing directive编写 C++ 正则表达式以匹配 #include 预处理指令
【发布时间】:2014-10-22 17:10:25
【问题描述】:

我想用 C++ 编写一个正则表达式来匹配 #include 预处理指令。 所以我写了这个:

std::regex includePattern("^[[:blank:]|[:space:]]*#[[:blank:]|[:space:]]*include[[:blank:]|[:space:]]+[<|\"]{1}[_[:alpha:]]+[_[:alnum:]]*");

这适用于:

std::string matchString = "#include <vector>";

但只匹配字符串的一部分,不包括结尾的“>”, 但如果我将正则表达式更改为:

std::regex includePattern("^[[:blank:]|[:space:]]*#[[:blank:]|[:space:]]*include[[:blank:]|[:space:]]+[<|\"]{1}[_[:alpha:]]+[_[:alnum:]]*[>|\"]{1}");

它不会给我想要的结果,只是告诉我“找不到”!有什么问题吗?

谁能帮我用 C++ 编写一个准确的正则表达式来匹配 #include 预处理指令?

提前致谢!

【问题讨论】:

  • 使用 or 或 [[:space:]][[:blank:]] 是没有意义的:匹配 [[:blank:]] 的所有内容也匹配 [[:space:]]
  • 另外,将{1} 放在字符类之后是没有意义的;这是默认设置。
  • 而且您不应该将| 放在字符类中。一个字符类一个或;在字符类中,| 按字面意思处理。 (这些都不能解释为什么你的第二个表达式不起作用。)
  • #includes 可能会被遮挡,隐藏在 cmets /* */ 中。除非你同时处理 cmets,否则你永远不会知道。

标签: c++ regex include


【解决方案1】:

这取决于要匹配的输入是否可能包含新的 线? [[:space:]] 将匹配任何空白,包括新的 行,[[:blank:]] 将匹配除新行之外的任何空白 (我不确定标准是否支持它)。反正, 类似:

"^\\s*#\\s*include\\s+[<\"][^>\"]*[>\"]\\s*"

应该可以,但是...

  • 如果您的源代码有不应该的新行,它仍然 可能匹配。

  • 如果您的源代码已经转义了新行,比如说在 令牌include 或文件名,它不会匹配。 (这是 合法的 C++,但没有一个头脑正常的人会这样做。)

  • 如果您的来源有不匹配的分隔符," 在一端, 和 &lt;&lt; 在另一个,它仍然会匹配。

  • 而且它不处理行尾的 cmets。处理 C++ 风格的 cmets (//) 应该只是添加的问题 "(?://.*)?" 到表达式的末尾。处理 C 风格 cmets (特别是因为可以有几个)有点多 复杂。

为确保分隔符匹配,您可能必须输入 包含在或之后的所有内容:

"^\\s*#\\s*include\\s+(?:<[^>]*>|\"[^\"]*\")\\s*"

同样,您需要在末尾添加以处理 cmets。

【讨论】:

  • 第三个[:space:]需要额外的一层[],我认为你应该修复"的转义。
  • @nhahtdh 我在发布后不久就发现了[:space:] 的问题,并更正了它以使用更简单的\\s。我刚刚更正了第二个表达式以使用\\s
【解决方案2】:

你不是在验证吗?
有一件事,您可以指望包含在 BOL 和可能的空格之后出现。
并在其右侧用空格分隔。
除此之外,我不会尝试验证右边的内容。

仅使用 多行 修饰符 -
"(?m)^[^\\S\\r\\n]*#include[^\\S\\r\\n]+(.*?)[^\\S\\r\\n]*"

展开:

 (?m)
 ^ [^\S\r\n]* 
 \#include
 [^\S\r\n]+ 
 ( .*? )               # (1)
 [^\S\r\n]* 

【讨论】:

    【解决方案3】:

    如果您需要捕获包含类型 &lt;" 以及您可以使用的包含文件名:

    std::string reg = "\\s*#\\s*include\\s*([<\"])([^>\"]+)([>\"])"; // escaped version
    

    - 或 -

    std::string raw = R"reg(\s*#\s*include\s*([<"])([^>"]+)([>"]))reg"; // raw string version
    

    Live Demo

    Group 1 = `<` or `"`
    Group 2 = file name
    Group 3 = `>` or `"`
    

    【讨论】:

      【解决方案4】:

      以下正则表达式将匹配#include 指令,例如#include &lt;vector&gt;

      ^#include\s+<\w+>$
      

      注意:这不包括诸如#include stdio.h 之类的指令。

      【讨论】:

      • 它也不适用于任何用户标题(至少通常如此)。
      • @JamesKanze 这是真的。 OP 只提供了一个例子来验证,所以我在满足提供的例子的同时尽量让它简单。
      猜你喜欢
      • 1970-01-01
      • 2010-09-08
      • 2021-09-21
      • 1970-01-01
      • 1970-01-01
      • 2018-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多