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

通过regex提取样式表

  •  1
  • BMBM  · 技术社区  · 14 年前

    是的,我知道,我知道,用正则表达式解析HTML是非常糟糕的。但是我正在处理应该提取所有 link style HTML页中的元素。我会把它换成 dom 但是在regex之后有一个很大的代码块依赖于 preg_match_all 返回匹配的结果。

    脚本正在使用此regex:

    $pattern = '/<(link|style)(?=.+?(?:type="(text\/css)"|>))(?=.+?(?:media="(.*?)"|>))(?=.+?(?:href="(.*?)"|>))(?=.+?(?:rel="(.*?)"|>))[^>]+?\2[^>]+?(?:\/>|<\/style>)\s*/is';
    
    preg_match_all($pattern, $htmlContent, $cssTags);
    

    但它不起作用。没有匹配的元素。不幸的是,我真的很讨厌雷鬼,所以如果有人能帮我,那就太好了。

    4 回复  |  直到 14 年前
        1
  •  1
  •   gblazex    14 年前

    我会把这个问题分成几个小问题。写起来容易,维护起来也容易。当然还有更多的代码行。一个巨大的regex的问题是有许多gotcha,输入可能无效,这很难在一个大的模式中管理。

    /<link([^>]+)>/
    -> extract attributes:
       /([\w]+)\s*=\s*"([^"]*)"/
    
    /<style[^>]*>(.+?)</style>/
    -> extract inline styles
    

    最后将结果合并到一个数组中,就好像preg-match-u生成了它一样。

        2
  •  0
  •   Jan Goyvaerts    14 年前

    如果我使用正则表达式来完成这项工作,例如,因为您需要能够处理无效的HTML,而使用适当的解析器通常很困难,那么我将使用单独的正则表达式。使用一个或两个正则表达式获取 style link 标记,并使用另一组regex从每个标记中获取各种属性。

    您的regex尝试通过使用lookahead反复扫描opening标签来获取所有元素,从而一次性完成所有操作。在只使用一个regex的情况下,这是一个很好的技巧,但在编写自己的代码时,这不是推荐的方法。

    我对你的瑞格鞋做了一些改进。我取代了 .*? .+? 在可能的情况下使用否定字符类来提高效率。您的regex不工作的原因是它没有正确地尝试匹配结束标记或正确地处理 链接 没有结束标记的标记。我确定了。

    正则表达式:

    <(link|style)(?=[^<>]*?(?:type="(text/css)"|>))(?=[^<>]*?(?:media="([^<>"]*)"|>))(?=[^<>]*?(?:href="(.*?)"|>))(?=[^<>]*(?:rel="([^<>"]*)"|>))(?:.*?</\1>|[^<>]*>)
    

    PHP:

    $pattern = '%<(link|style)(?=[^<>]*?(?:type="(text/css)"|>))(?=[^<>]*?(?:media="([^<>"]*)"|>))(?=[^<>]*?(?:href="(.*?)"|>))(?=[^<>]*(?:rel="([^<>"]*)"|>))(?:.*?</\1>|[^<>]*>)%si'
    
        3
  •  0
  •   BMBM    14 年前

    完全感谢您的回答,但我最终还是用dom扩展重写了这个位。这应该会使它变得更加健壮。

        4
  •  0
  •   tim    8 年前

    仅获取外部资源:

    preg_match_all('#(<link\s(?:[^>]*rel="stylesheet")[^>]*>)\R?#is', $content, $matches, PREG_SET_ORDER)