C++ 正则表达式:获取 SubMatch 匹配到的捕获组的索引
C++ regex: Get index of the Capture Group the SubMatch matched to
上下文。我正在开发一个 Lexer/Tokenizing 引擎,它将使用正则表达式作为后端。词法分析器接受定义标记 types/IDs 的规则,例如
<identifier> = "\b\w+\b"
.
正如我所设想的那样,要进行基于正则表达式匹配的标记化,正则表达式定义的所有规则都包含在捕获组中,并且所有组都由 OR 分隔。
在执行匹配时,我们生成的每个匹配项 必须具有匹配到的捕获组的索引 。我们使用这些 ID 将匹配项映射到令牌类型。
所以本题的问题就出现了——如何获取群的ID?
Similar question 在这里,但它没有提供我的具体问题的解决方案。
正是我的问题 here,但它在 JS 中,我需要一个 C/C++ 解决方案。
假设我有一个正则表达式,由用 OR 分隔的捕获组组成:
(\b[a-zA-Z]+\b)|(\b\d+\b)
匹配整个数字或字母词。
我的问题要求正则表达式子匹配所匹配的捕获组的索引是已知的,例如匹配字符串时
foo bar 123
3 次迭代将完成。每次迭代的匹配组索引将为 0 0 1
,因为前两个匹配匹配第一个捕获组,最后一个匹配匹配第二个捕获组。
我知道在标准 std::regex
库中这并非完全可行(regex_token_iterator
不是解决方案,因为我不需要跳过任何匹配项)。
我对 boost::regex
或 PCRE 正则表达式库了解不多。
完成此任务的最佳方法是什么?使用哪个库和方法?
可以用sregex_iterator
得到所有的匹配,一旦有匹配可以分析std::match_results
结构,只抓取参与组的ID-1值匹配(注意这里只有一组会匹配,第一个或第二个),可以使用 m[index].matched
:
方便地检查
std::regex r(R"((\b[[:alpha:]]+\b)|(\b\d+\b))");
std::string s = "foo bar 123";
for(std::sregex_iterator i = std::sregex_iterator(s.begin(), s.end(), r);
i != std::sregex_iterator();
++i)
{
std::smatch m = *i;
std::cout << "Match value: " << m.str() << " at Position " << m.position() << '\n';
for(auto index = 1; index < m.size(); ++index ){
if (m[index].matched) {
std::cout << "Capture group ID: " << index-1 << std::endl;
break;
}
}
}
见C++ demo。输出:
Match value: foo at Position 0
Capture group ID: 0
Match value: bar at Position 4
Capture group ID: 0
Match value: 123 at Position 8
Capture group ID: 1
请注意,R"(...)"
是原始字符串文字,不需要在其中加双反斜杠。
此外,index
在 for
循环开始时设置为 1
因为第 0 组是整个匹配项,但您希望组 ID 从零开始, 这就是为什么后面减去 1
的原因。
上下文。我正在开发一个 Lexer/Tokenizing 引擎,它将使用正则表达式作为后端。词法分析器接受定义标记 types/IDs 的规则,例如
<identifier> = "\b\w+\b"
.
正如我所设想的那样,要进行基于正则表达式匹配的标记化,正则表达式定义的所有规则都包含在捕获组中,并且所有组都由 OR 分隔。
在执行匹配时,我们生成的每个匹配项 必须具有匹配到的捕获组的索引 。我们使用这些 ID 将匹配项映射到令牌类型。
所以本题的问题就出现了——如何获取群的ID?
Similar question 在这里,但它没有提供我的具体问题的解决方案。
正是我的问题 here,但它在 JS 中,我需要一个 C/C++ 解决方案。
假设我有一个正则表达式,由用 OR 分隔的捕获组组成:
(\b[a-zA-Z]+\b)|(\b\d+\b)
匹配整个数字或字母词。
我的问题要求正则表达式子匹配所匹配的捕获组的索引是已知的,例如匹配字符串时
foo bar 123
3 次迭代将完成。每次迭代的匹配组索引将为 0 0 1
,因为前两个匹配匹配第一个捕获组,最后一个匹配匹配第二个捕获组。
我知道在标准 std::regex
库中这并非完全可行(regex_token_iterator
不是解决方案,因为我不需要跳过任何匹配项)。
我对 boost::regex
或 PCRE 正则表达式库了解不多。
完成此任务的最佳方法是什么?使用哪个库和方法?
可以用sregex_iterator
得到所有的匹配,一旦有匹配可以分析std::match_results
结构,只抓取参与组的ID-1值匹配(注意这里只有一组会匹配,第一个或第二个),可以使用 m[index].matched
:
std::regex r(R"((\b[[:alpha:]]+\b)|(\b\d+\b))");
std::string s = "foo bar 123";
for(std::sregex_iterator i = std::sregex_iterator(s.begin(), s.end(), r);
i != std::sregex_iterator();
++i)
{
std::smatch m = *i;
std::cout << "Match value: " << m.str() << " at Position " << m.position() << '\n';
for(auto index = 1; index < m.size(); ++index ){
if (m[index].matched) {
std::cout << "Capture group ID: " << index-1 << std::endl;
break;
}
}
}
见C++ demo。输出:
Match value: foo at Position 0
Capture group ID: 0
Match value: bar at Position 4
Capture group ID: 0
Match value: 123 at Position 8
Capture group ID: 1
请注意,R"(...)"
是原始字符串文字,不需要在其中加双反斜杠。
此外,index
在 for
循环开始时设置为 1
因为第 0 组是整个匹配项,但您希望组 ID 从零开始, 这就是为什么后面减去 1
的原因。