我想使用空格作为我的分隔符来分割我的句子,但转义的空格除外。使用 boost::split 和正则表达式,如何拆分它?如果不可能,还有什么办法?
例子:
std::string sentence = "My dog Fluffy\\ Cake likes to jump";
结果:
我的
狗
蓬松\蛋糕
喜欢
到
跳跃
最佳答案
三种实现方式:
- 拥有 boost spirit
- 使用 Boost 正则表达式
- 手写解析器
boost spirit
以下是我如何使用 Boost Spirit 执行此操作。这似乎有些过分,但经验告诉我,一旦您拆分输入文本,您可能需要更多的解析逻辑。
当您从“仅拆分标记”扩展到具有生产规则的真实语法时,Boost Spirit 会大放异彩。
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
int main() {
std::string const sentence = "My dog Fluffy\\ Cake likes to jump";
using It = std::string::const_iterator;
It f = sentence.begin(), l = sentence.end();
std::vector<std::string> words;
bool ok = qi::phrase_parse(f, l,
*qi::lexeme [ +('\\' >> qi::char_ | qi::graph) ], // words
qi::space - "\\ ", // skipper
words);
if (ok) {
std::cout << "Parsed:\n";
for (auto& w : words)
std::cout << "\t'" << w << "'\n";
} else {
std::cout << "Parse failed\n";
}
if (f != l)
std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n";
}
使用 Boost 正则表达式
这看起来很简洁但是
- 需要链接到 boost_regex
- 在断言背后使用“黑魔法”负面观察:http://www.regular-expressions.info/lookaround.html
#include <iostream>
#include <boost/regex.hpp>
#include <boost/algorithm/string_regex.hpp>
#include <vector>
int main() {
std::string const sentence = "My dog Fluffy\\ Cake likes to jump";
std::vector<std::string> words;
boost::algorithm::split_regex(words, sentence, boost::regex("(?<!\\\\)\\s"), boost::match_default);
for (auto& w : words)
std::cout << " '" << w << "'\n";
}
Using c++11 raw literals you could write the regular expression slightly less obscurely:
boost::regex(R"((?<!\\)\s)")
, meaning "any whitespace not following a backslash"
手写解析器
这有点乏味,但是像 Spirit 语法一样是完全通用的,并且性能不错。
但是,一旦您开始向语法添加复杂性,它就不会像 Spirit 方法那样优雅地扩展。一个优点是与 Spirit 版本相比,您编译代码所花费的时间更少。
#include <iostream>
#include <iterator>
#include <vector>
template <typename It, typename Out>
Out tokens(It f, It l, Out out) {
std::string accum;
auto flush = [&] {
if (!accum.empty()) {
*out++ = accum;
accum.resize(0);
}
};
while (f!=l) {
switch(*f) {
case '\\':
if (++f!=l && *f==' ')
accum += ' ';
else
accum += '\\';
break;
case ' ': case '\t': case '\r': case '\n':
++f;
flush();
break;
default:
accum += *f++;
}
}
flush();
return out;
}
int main() {
std::string const sentence = "My dog Fluffy\\ Cake likes to jump";
std::vector<std::string> words;
tokens(sentence.begin(), sentence.end(), back_inserter(words));
for (auto& w : words)
std::cout << "\t'" << w << "'\n";
}
关于c++ - 如何用转义空格分割句子?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29380897/