0

我正在尝试为 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

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

关于我只期待一个结果时为什么会得到多个结果的任何想法?

4

2 回答 2

2

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

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

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

\s+ ... \s*

字符串的其余部分由

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

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

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

\bin\s+[a-zA-Z0-9]+\s+[a-zA-Z0-9_]+\s*(?:\[[0-9]+\])?\s*
于 2013-06-15T03:43:13.280 回答
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*;

包括圆括号()。圆括号创建一个“组”又名“子表达式”。因为子表达式是可选的“(....)?”,所以即使子表达式没有真正匹配任何内容,也允许整个表达式匹配。当子表达式不匹配任何内容时,该子表达式的值为空字符串。有关“捕获括号”和“非捕获括号”的更多信息,请参阅“正则表达式:使用圆括号进行分组”。

根据regex_search 的文档

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

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

于 2013-06-15T11:45:23.553 回答