C++正则表达式
开头
这两天在写引擎二周目,复健C++,遇到一些问题记录一下
需求
写一个shader系统,需要自动分析出定义变量的名称
例如
1 | ..... |
我需要知道这个uniform变量的名称和类型
可以使用如下正则表达式
1 | (?<=uniform\s+sampler2D\s+)(\S+)(?=;) |
?<=
表示根据后面的字符串(“uniform sampler2D “),后向匹配后方字符串,但是最后匹配结果中不保存”uniform sampler2D “
+
表示前一个字符或者子串,匹配1-无限次.
*
表示前一个字符或者子串,匹配0-无限次.
?=
表示根据后面的字符串(“;”),前向匹配字符串,但是最后结果中不保存”;”
\S
(大写S)表示匹配一个非空白字符,只匹配一个.所以要加上+
,表示前一个字符需要匹配至少一次.
\s
(小写s)表示匹配一个空白字符,只匹配一个.上+
号的目的是为了防止某些小可爱在中间乱打空格.
\w
(小写)表示匹配一个无特殊符号的”字”字符,也就是[0-9a-zA-Z_].注意最后是下划线.
()
表示其中的字符串形成一组子串并且保存到最终结果中.所以()
中?
的作用表示这个子串不保存.
这样就能得到最终字符串TINY_TexColor
问题
问题是C++的std::regex
他喵的不支持后向查看.所以需要换一种方式来写.
1 | R"(uniform\s+sampler2D\s+(\w+)(?=;))" |
R”()”表示其中字符串的转义字符不需要转义.
于是使用如下C++代码就能得到结果TINY_TexColor
.
1 | std::string test = "uniform sampler2D TINY_TexColor;"; |
由于C++自己的特性,std::smath
在使用std::regex_search
之后,0号位置一定会保存整个被匹配到的字符串,也就是”uniform sampler2D TINY_TexColor”.注意不包含’;’因为前向查看给否决了.
所以1号位置才是我们想要的结果.
为什么会有这样的结果?
因为()
表达式表示保存这个匹配到的字符串,所以()
中的内容就会被保存到结果中,并且因为这是第一个被保存的子串,所以它的index为1.
更进一步
根据以上规则,我们还可以进一步,继续提取这个uniform的类型信息.
1 | std::string test = "uniform sampler2D TINY_TexColor;"; |
用(\w+)
替换掉sampler2D
所在的位置,注意这样写以后sampler2D
的位置就成了第一个()
保存的子串所在的位置了,变量名称就顺移到了下一位,即2的位置.
完成
所以使用如下代码,就能匹配出shader文件中所有的uniform变量类型和名称
1 | std::string new_content = "all shader text"; |
std::sregex_iterator
会在每一个迭代周期进行进行一次std::regex_search
对迭代器解引用就可以获得内部存在的match_results
.
最后根据规则直接取变量就行了.