【问题标题】:Get sub-strings between two non-unique strings in text获取文本中两个非唯一字符串之间的子字符串
【发布时间】: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 循环执行得更好。

标签: c++ regex


【解决方案1】:

首先让你的模式非贪婪
.*.*? 以便匹配尽可能短。它会是这样的:

"(.*?)"

然后关于 中的std:regex 库,请参阅此链接,这是我对这个库的体验。

std regex_search to match only current line

【讨论】:

  • 谢谢!虽然我看到这个社区非常鄙视正则表达式来解析 HTML 或 XML 代码,但这至少给了我一种可以使用的方法。虽然我认真对待这个建议并尝试使用基本的 std::string 函数来实现这一点。
  • @JagdishRapata。不客气 :)。对于这样的事情,使用正则表达式是正确的。只知道 C++ 正则表达式有很多错误。
猜你喜欢
  • 1970-01-01
  • 2013-09-12
  • 1970-01-01
  • 2015-06-24
  • 1970-01-01
  • 2012-12-28
  • 2014-04-02
相关资源
最近更新 更多