【发布时间】:2018-02-09 10:13:28
【问题描述】:
我正在尝试从基本上是 XML 的 std::string 中提取 xml 属性。我没有使用 XML 解析器或 std 之外的任何东西的奢侈,但请注意,我只是专门寻找这个特定的 xml 属性,而不是真正解析 xml。仅仅为这个特定的提取过程集成一个库/解析器是没有意义的。
一个示例字符串:
<Params>
<Element Name="elem(1)"/>
<Some Value="10"/>
<Element Name="elem(2)" />
<Attr Value="40" />
</Params>
我需要提取的字符串具体是: elem(1) 和 elem(2)
所以为了匹配,我使用了 start 和 end 变量
start string is "<Element Name=\"" and string end "\""
我把这段代码放在一起,显然是在许多 SO 文章中搜索的:
int main()
{
const std::string s = "<Element Name=\"elem(1)\"/> <Some Value=\"10\" Unit=\"m\"/> <Element Name=\"elem(2)\"/> <Attr Value=\"40\" />";
std::string start = "<Element Name=\"";
std::string end = "\"";
std::regex words_regex(start + "(.*)" + end);
auto words_begin = std::sregex_iterator(s.begin(), s.end(), words_regex);
auto words_end = std::sregex_iterator();
std::cout << "Found "
<< std::distance(words_begin, words_end)
<< " words:\n";
for (std::sregex_iterator i = words_begin; i != words_end; ++i) {
std::smatch match = *i;
std::string match_str = match.str();
std::cout << match_str << '\n';
}
}
问题是它返回以最后一个双引号结尾的整个字符串。我将处理收集多个子字符串的部分。但首先我需要确保正则表达式至少正确返回第一个子字符串。
我看到很多关于正则表达式的积极前瞻性的提及并试图理解它。但我还不能让它与 std::regex 一起工作。是否完全支持? (在 Visual Studio 2015 和 GCC 4.8.2 上编译)
也欢迎使用其他解决方案,只要它们不涉及第三方库并且可以使用标准 C++11 代码实现。
【问题讨论】:
-
您说使用 XML 解析器没有意义,但根据您的代码范围,它最终可能有意义。如果您只是想在 XML 中获取特定属性,那么使用正则表达式来做到这一点比使用解析器更更没有意义。如果您不能使用 XML 解析器,那就另当别论了。但如果可以的话,我强烈建议使用一个。我还建议查看famous answer。对于咯咯笑,也是因为它抓住了问题。
-
@JBL 此代码是模块的一部分,除了这一位之外,不涉及 XML 解析(在其他地方完成)。我可能用错误的措辞说“没有意义”,而它应该更多的是“无法在此处使用解析器”。
-
让你的模式不贪婪。将
.*转换为.*?并查看this link -
在这里阅读我的答案 => std regex_search to match only current line
-
@ShakibaMoshiri 谢谢!我现在得到了完美的结果!您可以将此作为答案发布吗?此外,我正在慢慢理解正则表达式并不是许多字符串解析问题的真正答案。我的信念(没有任何实际测试)是 std::regex 将比粗略编写的带有 .find() 和迭代器的 for 循环执行得更好。