从[Spirit-general]列表中迁移
早上好,
我试图在4 std::strings
之间解析一个相对简单的模式,
提取与模式匹配的任何部分到一个单独的
std::string
。
从抽象的意义上说,这就是我想要的:
s1=<string1><consecutive number>, s2=<consecutive number><string2>,
s3=<string1><consecutive number>, s4=<consecutive number><string2>
少抽象:
s1="apple 1", s2="2 cheese", s3="apple 3", s4="4 cheese"
实际内容:
s1="lxckvjlxcjvlkjlkje xvcjxzlvcj wqrej lxvcjz ljvl;x czvouzxvcu
j;ljfds apple 1 xcvljxclvjx oueroi xcvzlkjv; zjx", s2="xzljlkxvc
jlkjxzvl jxcvljzx lvjlkj wre 2 cheese", s3="apple 3", s4="kxclvj
xcvjlxk jcvljxlck jxcvl 4 cheese"
我如何进行此模式匹配?
感谢所有建议,
Alec Taylor
更新2
这是一个非常简单的解释,我只想解释一下 我试图解决的问题:
std::string s1=garbagetext1+number1+name1+garbagetext4; std::string s3=garbagetext2+(number1+2)+name1+garbagetext5; std::string s5=garbagetext3+(number1+4)+name1+garbagetext6;
编辑:
随意添加到stackoverflow(我遇到了一些麻烦 张贴那里)
我无法告诉你到目前为止我做过的事情,因为我不确定是不是 是在boost :: spirit库的功能范围内做什么的 我正在尝试
答案 0 :(得分:4)
修改:重新 Update2
这是一个非常简单的解释,我只想解释一下 我试图解决的问题:
std::string s1=garbagetext1+number1+name1+garbagetext4; std::string s3=garbagetext2+(number1+2)+name1+garbagetext5; std::string s5=garbagetext3+(number1+4)+name1+garbagetext6;
它开始看起来像是一份工作:
qi::symbol
)可以促进它,但我觉得你可以用多种方式写出来)这是一个简单的想法:
(\d+) ([a-z]+).*?(\d+) \2
\d+
匹配“(子表达式)”(NUM1
)([a-z]+)
匹配名称(只选择了'name'的简单定义).*?
跳过任何长度的垃圾,但在开始后续比赛之前尽可能少\d+
匹配另一个数字(数字序列)(NUM2
)\2
后跟相同 名称( backreference )你可以看到你如何缩小匹配列表以检查“潜在”命中。您只需要/后验证/看到NUM2 == NUM1 + 2
两个注释:
在尾部周围添加(...)+
以允许重复匹配模式
(\d+) ([a-z]+)(.*?(\d+) \2)+
您可能希望垃圾跳过(.*?
)了解分隔符(通过执行 negative zerowidth assertions )以避免超过2个跳过分隔符(例如{ {1}}作为分隔模式)。为了清楚起见,我现在把它放在范围之外,这是要点:
s\d+="
Alec,以下是在回答你的问题时如何在Boost Spirit中做各种事情的展示案例。
我必须对所需的输入结构做出假设;我假设
注意下面的实施中有大约十几个地方,可能会做出明显不那么复杂的选择。例如,我可以硬编码整个模式(作为事实上的正则表达式?),假设输入中总是需要4个项目。但是我想
qi::locals<>
and inherited attributes的主题已经列入我的议程一段时间了。但是,该解决方案具有很大的灵活性:
((?!s\d+=").)*? -- beware of potential performance degradation
即可。请查看Unsigned Integer Parsers以了解如何调整该行为的信息)输出结构是s01="apple 001"
或struct的向量:
vector<std::pair<int, std::string> >
可以使用单struct Entry
{
int sequence;
std::string text;
};
行
该示例使用Boost Spirit Qi进行解析。 相反,Boost Spirit Karma用于显示解析结果:
#if 1/0
帖子中提供的 实际内容 的输出为:
format((('s' << auto_ << "=\"" << auto_) << "\"") % ", ", parsed)
代码。
parsed: s1="apple 1", s2="2 cheese", s3="apple 3", s4="4 cheese"
答案 1 :(得分:2)
如果您可以使用c ++ 11编译器,使用AX †解析这些模式非常简单:
#include <axe.h>
#include <string>
template<class I>
void num_value(I i1, I i2)
{
unsigned n;
unsigned next = 1;
// rule to match unsigned decimal number and compare it with another number
auto num = axe::r_udecimal(n) & axe::r_bool([&](...){ return n == next; });
// rule to match a single word
auto word = axe::r_alphastr();
// rule to match space characters
auto space = axe::r_any(" \t\n");
// semantic action - print to cout and increment next
auto e_cout = axe::e_ref([&](I i1, I i2)
{
std::cout << std::string(i1, i2) << '\n';
++next;
});
// there are only two patterns in this example
auto pattern1 = (word & +space & num) >> e_cout;
auto pattern2 = (num & +space & word) >> e_cout;
auto s1 = axe::r_find(pattern1);
auto s2 = axe::r_find(pattern2);
auto text = s1 & s2 & s1 & s2 & axe::r_end();
text(i1, i2);
}
要解析文本,只需调用num_value(text.begin(), text.end());
无需更改即可解析unicode字符串。
†我没有测试它。
答案 2 :(得分:0)
了解Boost.Regex。我已经在boost-users中看到了几乎相同的poosting,解决方案是使用正则表达式进行一些匹配工作。