0

首先让我说,我已经彻底解决了这个问题的所有其他解决方案,虽然它们非常相似,但没有一个能完全解决我的问题。

我需要使用 boost regex 提取除引号之外的所有标记(对于引用的标记)。

我认为我需要使用的正则表达式是:

sregex pattern = sregex::compile("\"(?P<token>[^\"]*)\"|(?P<token>\\S+)");

但我得到一个错误:

命名标记已存在

为 C# 发布的解决方案似乎适用于重复的命名标记,因为它是与另一个标记的 OR 表达式。

正则表达式在空格上拆分,除非在引号中

4

3 回答 3

3

我在这里回答了一个非常相似的问题:

如何使我的拆分仅在一条真实行上工作并能够跳过字符串的引用部分?

示例代码

  • 使用 Boost Spirit
  • 支持带引号的字符串、部分带引号的字段、用户定义的分隔符、转义引号
  • 一般支持许多(不同的)输出容器
  • 支持 Range 概念的模型作为输入(包括 char[],例如)

使用相对广泛的编译器版本和 Boost 版本进行测试。

https://gist.github.com/bcfbe2b5f071c7d153a0

于 2011-10-24T07:30:32.773 回答
0

大多数正则表达式风格不允许重用组名。如果所有用途都在相同的交替范围内,则某些口味允许使用它,但显然您的用途不是其中之一。但是,如果您运行的是最新版本的 Boost,您应该能够使用分支重置组。它看起来像这样 -(?|...|...|...)在每个备选方案中,组编号重置为到达分支重置组之前的任何位置。它也应该适用于命名组,但这不能保证。我无法自己测试它,所以试试这个:

"(?|\"(?P<token>[^\"]*)\"|(?P<token>\\S+))"

...如果这不起作用,请尝试使用普通的旧编号组。

于 2011-10-24T06:59:54.760 回答
0

在这里查看答案时,我测试了另一种方法,该方法涉及使用不同的组标记名称,并在迭代它们时简单地测试哪个是空白的。虽然它可能不是最快的代码,但它是迄今为止最易读的解决方案,这对我的问题更重要。

这是对我有用的代码:

    #include <boost/xpressive/xpressive.hpp>
    using namespace boost::xpressive;
...
    std::vector<std::string> tokens;
    std::string input = "here is a \"test string\"";
    sregex pattern = sregex::compile("\"(?P<quoted>[^\"]*)\"|(?P<unquoted>\\S+)");
    sregex_iterator cur( input.begin(), input.end(), pattern );
    sregex_iterator end;

    while(cur != end)
    {
      smatch const &what = *cur;
      if(what["quoted"].length() > 0)
      {
        tokens.push_back(what["quoted"]);
      }
      else
      {
        tokens.push_back(what["unquoted"]);
      }
      cur++;
    }
于 2011-10-27T03:23:07.817 回答