首先让我说,我已经彻底解决了这个问题的所有其他解决方案,尽管它们非常相似,但没有一个能完全解决我的问题。
我需要使用boost正则表达式提取所有标记,不包括引号(对于引用的标记)。
我认为我需要使用的正则表达式是:
sregex pattern = sregex::compile("\"(?P<token>[^\"]*)\"|(?P<token>\\S+)");
但我收到错误:
命名标记已存在
为C#发布的解决方案似乎与重复的命名标记一起使用,因为它是与另一个的OR表达式。
答案 0 :(得分:3)
我在这里回答了一个非常相似的问题:
How to make my split work only on one real line and be capable to skip quoted parts of string?
示例代码
使用相对广泛的编译器版本和Boost版本进行测试。
答案 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++;
}