标记一个字符串,不包括引号内的分隔符

时间:2011-10-24 05:49:03

标签: c++ regex boost boost-regex boost-xpressive

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

我需要使用boost正则表达式提取所有标记,不包括引号(对于引用的标记)。

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

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

但我收到错误:

  

命名标记已存在

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

Regular Expression to split on spaces unless in quotes

3 个答案:

答案 0 :(得分:3)

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

How to make my split work only on one real line and be capable to skip quoted parts of string?

示例代码

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

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

https://gist.github.com/bcfbe2b5f071c7d153a0

答案 1 :(得分:0)

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

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

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

答案 2 :(得分: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++;
    }