0

我忘记正则表达式的速度比我母亲的生日快。这是一个主要的 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;
  }

第 4 个捕获组是我大惊小怪的,尤其是对单词进行标记。但我不需要它,所以我的工作完成了。但是,我仍然想知道如何标记一个以 '\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 中进行屏幕抓取时,我会通过对正文重复应用正则表达式直到它用完标记来在文本正文中找到标记。

4

2 回答 2

1

这让我想起了一个类似的问题,Capturing repeating subpatterns in Python regex

如果空格分隔的单词的数量被限制在某个最大数量的标记,那么你可以添加一大堆额外的子模式,有点像:

"HTTP/(\\d+?)\\.(\\d+?) (\\d+?) ([^ ]+\s)?([^ ]+\s)?([^ ]+\s)?([^ ]+\s)?\n\r"

这当然是可怕的。

如果您想要一个嵌套组,我认为在您的正则表达式实现中没有“重复子模式”支持就无法做到这一点(请参阅regex链接问题中使用的 Python 的非标准模块。)使用基本字符串几乎肯定会更好函数 - 本地等效的string.split().

于 2012-03-27T15:21:04.760 回答
0

Boost可能能够进行递归分组,不确定。我倾向于它不能。
我只知道可以做到这一点的.NET。

您可以设计一个包含两个部分的正则表达式。第一部分捕获特定组,第二部分捕获一个组中的所有其余部分。然后,您可以对捕获的第二部分执行另一个递归正则表达式。

像这样的东西:
(specific)(part)(to)(capture)(all the remaining text)

然后对上一个剩余的文本捕获执行一段时间(/(part)/)正则表达式。

这是你如何在提升中做到这一点 -

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;
于 2012-03-27T21:50:55.603 回答