我正在尝试为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
当我提供整个文件作为输入时,我最终想要生成多个结果,但我希望得到一些一致性,以便我能够以一致的方式处理结果。
当我只期待一个结果时,为什么我会得到多个结果?
答案 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 - 一个匹配完整正则表达式,一个匹配子表达式 - 即使该子表达式并不真正匹配任何东西,因此也是空字符串。