为什么我会得到多个正则表达式匹配?

时间:2013-06-15 02:42:32

标签: c++ regex glsl

我正在尝试为GLSL着色器代码编写处理器,这将允许我分析代码并动态确定每个着色器需要处理的输入和输出。

为了实现这一点,我决定使用一些正则表达式来解析着色器代码,然后再通过OpenGL进行编译。

我已经编写了一些测试代码来验证正则表达式是否正常工作。

代码:

#include <iostream>
#include <string>
#include <regex>

using namespace std;

int main()
{

string strInput = "      in   vec3   i_vPosition;    ";
smatch match;
// Will appear in regex as:
//   \bin\s+[a-zA-Z0-9]+\s+[a-zA-Z0-9_]+\s*(\[[0-9]+\])?\s*;
regex rgx("\\bin\\s+[a-zA-Z0-9]+\\s+[a-zA-Z0-9_]+\\s*(\\[[0-9]+\\])?\\s*;");

bool bMatchFound = regex_search(strInput, match, rgx);

cout << "Match found: " << bMatchFound << endl;

for (int i = 0; i < match.size(); ++i)
{
    cout << "match " << i << " (" << match[i] << ") ";
    cout << "at position " << match.position(i) << std::endl;
}

}

唯一的问题是上面的代码生成两个结果而不是一个。虽然其中一个结果是空的。

输出:

Match found: 1
match 0 (in   vec3   i_vPosition;) at position 6
match 1 () at position 34

当我提供整个文件作为输入时,我最终想要生成多个结果,但我希望得到一些一致性,以便我能够以一致的方式处理结果。

当我只期待一个结果时,为什么我会得到多个结果?

2 个答案:

答案 0 :(得分:2)

您的正则表达式似乎包含反向引用

(\[[0-9]+\])?

它包含围绕1位或更多位数的方括号,但是?使它成为可选的。 应用正则表达式时,前导和尾随空格由

修剪
\s+ ... \s*

字符串的其余部分由

匹配
[a-zA-Z0-9]+\s+[a-zA-Z0-9_]+\s*

反向引用位匹配空字符串。

如果你想匹配任意包含该位的字符串,但不将其作为反向引用返回,请将其作为被动使用?:like:

\bin\s+[a-zA-Z0-9]+\s+[a-zA-Z0-9_]+\s*(?:\[[0-9]+\])?\s*

答案 1 :(得分:0)

  

我最终想要生成多个结果

regex_search只查找完整正则表达式的第一个匹配项。 如果要在源文本中找到完整正则表达式匹配的其他位置, 你必须反复运行regex_search。 看到 “C++ Regex to match words without punctuation” 例如,重复运行搜索。

  

上面的代码生成两个结果而不是一个。

令人困惑,不是吗?

正则表达式

\bin\s+[a-zA-Z0-9]+\s+[a-zA-Z0-9_]+\s*(\[[0-9]+\])?\s*;

包括圆括号()。 圆括号创建一个“组”又名“子表达式”。 因为子表达式是可选的“(....)?”, 即使子表达式没有真正匹配任何东西,也允许表达式作为整体匹配。 当子表达式与任何内容都不匹配时,该子表达式的值为空字符串。 有关“捕获括号”和“非捕获括号”的更多信息,请参阅"Regular-expressions: Use Round Brackets for Grouping"

根据documentation for regex_search

  • match.size()是子表达式的数量加1,
  • match[0]是源字符串中与完整正则表达式匹配的部分。
  • match[1]是源字符串中与正则表达式中第一个子表达式匹配的部分。
  • match[n]是源字符串中与正则表达式中第n个子表达式匹配的部分。

只有1个子表达式的正则表达式,如上例所示,将始终返回match.size()2 - 一个匹配完整正则表达式,一个匹配子表达式 - 即使该子表达式并不真正匹配任何东西,因此也是空字符串。