代码之家  ›  专栏  ›  技术社区  ›  nhaa123

Boost::regex问题,匹配HTML span元素

  •  1
  • nhaa123  · 技术社区  · 15 年前

    我不明白。我创建了这个正则表达式:

    <span class="copy[Green|Red].*>[\s]*(.*)[\s]*<\/span>
    

    <span class="copyGreen">0.12</span>
    <span class="copyRed">  0.12  </span>
    

    现在,这在RegexBuddy和其他人身上运行得很好,但在Boost::regex上运行得很好

    编辑:更准确地说,我想捕捉跨距之间的数字。前后 数字,也可以有空格(\n、\r等)。

    
    try {
            const boost::regex e("<span class=\"copy[Green|Red].*>[\\s]*(.*)[\\s]*<\\/span>");
            boost::smatch matches;
            std::string html("<span class=\"copyGreen\">  0.12  </span>");
    
            if (boost::regex_match(html, matches, e)) {
                    // Works... (not).
            } else {
                    throw std::runtime_error("Couldn't match the regex against HTML-source!");
            }
    } catch (boost::regex_error& e) {
            std::cout << e.what() << std::endl;
    }
    

    我做错了什么?提前谢谢!

    看来,正确的表达应该是

    boost::regex("<span class=\"copy(?:Green|Red)[^>]*>\\s*(.*?)\\s*<\\/span>"); // Thanks chaos!.

    这实际上与Boost匹配。但是,我需要启用boost::match_extra 为了获得我需要的所有捕获。这是通过定义

    BOOST_REGEX_MATCH_EXTRA

    在boost\regex\user.hpp中

    再次感谢你。

    3 回复  |  直到 15 年前
        1
  •  2
  •   chaos    15 年前

    首先,这是:

    [Green|Red]
    

    不会做你认为它会做的事。你想要:

    (?:Green|Red)
    

    [Green|Red] 是由字母组成的字符类 GRred| ,而不是在比赛之间交替的方式。按照您编写它的方式,它将恰好匹配这些字符中的一个,后跟任意数量的其他字符。

    这:

    [\s]
    

    \s
    

    为了你的第二个 \s 要工作,捕获表达式可能需要

    (.*?)
    

    我也建议你做第一件事 .* 进入 [^>]* ,以避免将其应用于实际HTML文档时会遇到的问题,因为实际HTML文档会吸收任意数量的HTML。

        2
  •  1
  •   Community Neeleshkumar S    7 年前
    [Green|Red]
    

    是错误的,因为[]表示 character class 在大多数正则表达式语法中。字符类基本上是可以匹配的字符组。例如,[abc]将匹配“a”、“b”或“c”。

    至于你的其他问题,有两种可能性,比如MacGuy提到的;(*)可能匹配得太多。为了确定,我需要看看你的正则表达式到底匹配什么。

    最后,您真的不应该使用正则表达式来解析HTML。它达到了一品脱,除了在最受控制的条件下和复杂的表达式之外,它根本不起作用。最好研究各种html/xml解析器。

    This 这是一个很好的解释为什么这是一个坏主意。

        3
  •  1
  •   SingleNegationElimination    15 年前

    你的正则表达式有几个问题。

    首先是这一点: [Green|Red]

    G , r , e , n , | , R d .

    你需要用亲权来做这件事,比如 (Green|Red) . 现在,这与字符串匹配 Green Red .

    编辑:如果您不想捕获任何内容,可以使用非捕获组,这在boost::regex中是通过包含 ?: 在第一个括号后: (?:Green|Red) . 现在正则表达式具有括号的分组行为,但没有捕获。

    (.*)

    这看起来不多,但匹配太多,包括像连续跨距这样的模式。这将消耗一个跨距的结束和下一个跨距的开始,一直到页面上的最后一个跨距。你需要让它不贪婪。在boost::regex中,您可以通过以下方法来实现 * 用一个 ? . 把它改成 (.*?) (并与其他*类似。

    问题是,除了简单的正则表达式之外,XML和HTML很难让任何东西正常工作。您真的应该使用一个用于处理该格式的库。有很多 options . 通过这种方式,您可以确保正确处理HTML,无论输入可能有多扭曲。