如何使用正则表达式匹配多个标记?
How to match multiple tokens using regular expressions?
我需要使用正则表达式来匹配特殊键和值。有个特殊情况不知道怎么办
字符串喜欢abcd/abcd
。我需要匹配 /
之前的所有单词。
所以我写(.)*/
,然后我发现它只匹配1个令牌(d)。更何况,即使匹配到我所需要的,我仍然不知道匹配了多少令牌。
那么正确的正则表达式应该是什么呢?实际情况比例子复杂很多,所以如果可以用正则表达式实现,我不想写tokenizer
为什么你的正则表达式不起作用
正则表达式 (.)*/
匹配任何字符,零次或多次,后跟 /
.
*
量词是 greedy,它会尽可能匹配。给定字符串"abcd/abcd",正则引擎匹配"abcd/abcd",然后匹配“/”失败,所以它回溯到"d",最后一步匹配“ /”。 ()
是一个组,您只捕获最后一个字符。
如何修复
[^\/]*
这匹配任何 不是 的“/”(请注意它已转义),这正是您想要的。如果你想捕获匹配的正则表达式,你应该将它更改为 ([^\/]*)
,现在第一组包含你的正则表达式。
请注意,根据您使用的语言,可能有很多解决方案,不一定是正则表达式。
您正在使用的 Boost 库提供了一种将重复组捕获到 堆栈 中的方法 提供 您使用 BOOST_REGEX_MATCH_EXTRA
标志设置,否则 what
将没有名为 captures
的成员。当您使用 boost::regex_search
或 boost::regex_match
时,传递 boost::match_extra
标志,您将使用 (.)*
捕获所有值(匹配和捕获换行符以外的任何字符,零个或多个出现)进入堆栈,可通过 sub_match
对象的 captures
成员访问。
这是来自 official Boost site 的演示方法:
#include <boost/regex.hpp>
#include <iostream>
void print_captures(const std::string& regx, const std::string& text)
{
boost::regex e(regx);
boost::smatch what;
std::cout << "Expression: \"" << regx << "\"\n";
std::cout << "Text: \"" << text << "\"\n";
if(boost::regex_match(text, what, e, boost::match_extra))
{
unsigned i, j;
std::cout << "** Match found **\n Sub-Expressions:\n";
for(i = 0; i < what.size(); ++i)
std::cout << " $" << i << " = \"" << what[i] << "\"\n";
std::cout << " Captures:\n";
for(i = 0; i < what.size(); ++i)
{
std::cout << " $" << i << " = {";
for(j = 0; j < what.captures(i).size(); ++j)
{
if(j)
std::cout << ", ";
else
std::cout << " ";
std::cout << "\"" << what.captures(i)[j] << "\"";
}
std::cout << " }\n";
}
}
else
{
std::cout << "** No Match found **\n";
}
}
int main(int , char* [])
{
print_captures("(.*)bar|(.*)bah", "abcbar");
return 0;
}
我需要使用正则表达式来匹配特殊键和值。有个特殊情况不知道怎么办
字符串喜欢abcd/abcd
。我需要匹配 /
之前的所有单词。
所以我写(.)*/
,然后我发现它只匹配1个令牌(d)。更何况,即使匹配到我所需要的,我仍然不知道匹配了多少令牌。
那么正确的正则表达式应该是什么呢?实际情况比例子复杂很多,所以如果可以用正则表达式实现,我不想写tokenizer
为什么你的正则表达式不起作用
正则表达式 (.)*/
匹配任何字符,零次或多次,后跟 /
.
*
量词是 greedy,它会尽可能匹配。给定字符串"abcd/abcd",正则引擎匹配"abcd/abcd",然后匹配“/”失败,所以它回溯到"d",最后一步匹配“ /”。 ()
是一个组,您只捕获最后一个字符。
如何修复
[^\/]*
这匹配任何 不是 的“/”(请注意它已转义),这正是您想要的。如果你想捕获匹配的正则表达式,你应该将它更改为 ([^\/]*)
,现在第一组包含你的正则表达式。
请注意,根据您使用的语言,可能有很多解决方案,不一定是正则表达式。
您正在使用的 Boost 库提供了一种将重复组捕获到 堆栈 中的方法 提供 您使用 BOOST_REGEX_MATCH_EXTRA
标志设置,否则 what
将没有名为 captures
的成员。当您使用 boost::regex_search
或 boost::regex_match
时,传递 boost::match_extra
标志,您将使用 (.)*
捕获所有值(匹配和捕获换行符以外的任何字符,零个或多个出现)进入堆栈,可通过 sub_match
对象的 captures
成员访问。
这是来自 official Boost site 的演示方法:
#include <boost/regex.hpp>
#include <iostream>
void print_captures(const std::string& regx, const std::string& text)
{
boost::regex e(regx);
boost::smatch what;
std::cout << "Expression: \"" << regx << "\"\n";
std::cout << "Text: \"" << text << "\"\n";
if(boost::regex_match(text, what, e, boost::match_extra))
{
unsigned i, j;
std::cout << "** Match found **\n Sub-Expressions:\n";
for(i = 0; i < what.size(); ++i)
std::cout << " $" << i << " = \"" << what[i] << "\"\n";
std::cout << " Captures:\n";
for(i = 0; i < what.size(); ++i)
{
std::cout << " $" << i << " = {";
for(j = 0; j < what.captures(i).size(); ++j)
{
if(j)
std::cout << ", ";
else
std::cout << " ";
std::cout << "\"" << what.captures(i)[j] << "\"";
}
std::cout << " }\n";
}
}
else
{
std::cout << "** No Match found **\n";
}
}
int main(int , char* [])
{
print_captures("(.*)bar|(.*)bah", "abcbar");
return 0;
}