我在母亲的生日那天忘记了正则表达式。这是一个主要的PITA。无论如何,我想要一个RE来解析HTTP响应状态行并正确捕获子元素。我得到了这个工作:
const boost::regex status_line("HTTP/(\\d+?)\\.(\\d+?) (\\d+?) (.*)\r\n");
std::string status_test1("HTTP/1.1 200 hassan ali\r\n");
boost::smatch what;
std::cout << regex_match(status_test1,what, status_line, boost::match_extra) << std::endl;
std::cout << what.size() << std::endl;
BOOST_FOREACH(std::string s, what)
{
std::cout << s << std::endl;
}
第四个捕获组是我所讨论的,特别是对这些词进行说明。但我不需要它,所以我的工作已经完成。但是,我仍然想知道如何标记一个空格分隔的句子,该句子以'\ 0'结尾,这会产生一个被剥离的单词的向量/数组。
我无法使用以下片段
const boost::regex sentence_re("(.+?)( (.+?))*");
boost::smatch sentence_what;
std::string sentence("hassan ali syed ");
std::cout << boost::regex_match(sentence,sentence_what,sentence_re, boost::match_extra) << std::endl;
BOOST_FOREACH(std::string s, sentence_what)
{
std::cout << s << std::endl;
}
它不应与"hassan ali syed "
匹配,但它应匹配"hassan ali syed"
,并且捕获组应输出hassan
ali
syed
(带换行符),但它会输出hassan
syed
syed
(请注意,第三个syed <space>syed
中的空格。我认为捕获组无法处理递归实体?
那么,是否有一种干净的方法可以在PCRE语法中指定一个标记化任务,从而产生一个干净的标记向量(不重复 - 即,我不希望嵌套组尝试剥离空白)。
我知道这不是工作的正确工具,spirit / lexx或boost :: tokenise是最好的,我知道这不是正确的方法。在.net中进行屏幕抓取时,我会在文本体中找到令牌,重复将正则表达式应用到正文中,直到它用完了令牌。
答案 0 :(得分:1)
这让我想起了一个类似的问题Capturing repeating subpatterns in Python regex。
如果以空格分隔的单词的数量被限制为某些最大的令牌数,那么你可以直接使用一大堆额外的子模式,有点像:
"HTTP/(\\d+?)\\.(\\d+?) (\\d+?) ([^ ]+\s)?([^ ]+\s)?([^ ]+\s)?([^ ]+\s)?\n\r"
这当然是可怕的。
如果你想要一个嵌套组,我不会认为这可以在你的regexp实现中没有“重复子模式”支持的情况下完成(参见Python中使用的非标准regex
模块链接的问题。)使用基本字符串函数 - 你当地的等价物string.split()
几乎肯定会更好。
答案 1 :(得分:0)
Boost可能能够进行递归分组,但不确定。我倾向于它不能 我只知道.NET可以做到这一点。
您可以设计一个包含两个部分的正则表达式。第一部分捕获特定组,第二部分捕获在一个组中所有其余组。然后,您可以在捕获的第二部分上执行另一个递归正则表达式。
这样的事情:
(specific)(part)(to)(capture)(all the remaining text)
然后对前一个剩余的文本捕获执行一段时间(/(部分)/)正则表达式。
以下是你如何在升级中做到这一点 -
const string status = "HTTP/1.1 200 hassan ali\r\n";
boost::regex rx_sentence ( "HTTP/(\\d+)\\.(\\d+)\\s+(\\d+)\\s*([^\\s]+(?:\\s+[^\\s]+)*)?.*" );
boost::regex rx_token ( "[^\\s]+" );
if ( boost::regex_match( status, what, rx_sentence) )
{
std::cout << "\nMatched:\n-----------------\n" << "'" << what[0] << "'" << std::endl;
std::cout << "\nStatus (match groups):\n-----------------" << std::endl;
for (int i=1; i < 4; i++)
{
std::cout << i << " = '" << what[i] << "'" << std::endl;
}
std::cout << "\nTokens (search of group 4):\n-----------------" << std::endl;
const string token_str = what[4];
std::string::const_iterator start = token_str.begin();
std::string::const_iterator end = token_str.end();
while ( boost::regex_search(start, end, what, rx_token) )
{
string token(what[0].first, what[0].second);
cout << "'" << token << "'" << endl;
start = what[0].second;
}
}
else
std::cout << "Didn't match" << std::endl;