【问题标题】:preg_match_all an array of items, then for each matchespreg_match_all 一个项目数组,然后对于每个匹配项
【发布时间】:2013-12-22 18:19:07
【问题描述】:

我正在编辑一些 Interspire 电子邮件代码。目前,该程序在发送之前会检查电子邮件的 HTML,并查找“a href”代码以替换链接。我希望它也能够通过并获取表单 action="" 并替换其中的 url(目前没有)。我想我可以使用这个堆栈帖子中的正则表达式:

PHP - Extract form action url from mailchimp subscribe form code using regex

但是我在思考如何处理数组时遇到了一些困难。仅执行 'a href=' 的当前代码如下:

    preg_match_all('%<a.+(href\s*=\s*(["\']?[^>"\']+?))\s*.+>%isU', $this->body['h'], $matches);
    $links_to_replace = $matches[2];
    $link_locations = $matches[1];

    arsort($link_locations);
    reset($links_to_replace);
    reset($link_locations);

    foreach ($link_locations as $tlinkid => $url) {
        // so we know whether we need to put quotes around the replaced url or not.
        $singles = false;
        $doubles = false;

        // make sure the quotes are matched up.
        // ie there is either 2 singles or 2 doubles.
        $quote_check = substr_count($url, "'");
        if (($quote_check % 2) != 0) {
        ...

我知道(或者我认为我知道),我需要将 preg_match_all 替换为:

    preg_match_all(array('%<a.+(href\s*=\s*(["\']?[^>"\']+?))\s*.+>%isU', '|form action="([^"]*?)" method="post" id="formid"|i'), $this->body['h'], $matches);

但是“$matches”是如何处理的呢?

$links_to_replace = $matches[2];
$link_locations = $matches[1];

仍然不成立是吗?有没有可能按照我的想法去做?或者我是否需要编写另一个函数来处理与 'a href' 分开的 'forms action='

【问题讨论】:

  • 看起来您正试图在preg_match_all() 中传递多个参数。为什么不直接使用preg_replace() 替换form action= url 或DOM?如果我假设正确,您想替换数组元素中的 url,最好使用 preg_replace_callback()
  • 如果要执行替换,为什么不使用 preg_replace 或 preg_replace_callback?
  • 我对 PHP 不是很精通,所以真的不知道最好的方法(或唯一的方法)去做事情。因此,如果我想添加一个功能,通常我只是离开已经存在的功能并尝试添加它。你是说 preg_match_all 行不通吗?我认为他们有理由使用它而不是 preg_replace()
  • 这取决于,就像我说的,如果你想找到所有form action= url,然后从数组元素中替换这些url,那么最好使用preg_replace_callback() 来执行此操作。如果不是这种情况,请更清楚地说明您到底想要做什么=)

标签: php regex arrays preg-match-all


【解决方案1】:

一个建议:

$pattern = <<<'LOD'
~
(?|            # branch reset feature: allows to have the same named
               # capturing group in an alternation. ("type" here)
    <a\s           # the link case
    (?>  # atomic group: possible content before the "href" attribute
        [^h>]++        # all that is not a "h" or the end of the tag ">"
      |
        \Bh++          # all "h" not preceded by a word boundary
      |
        h(?!ref\s*+=)  # all "h" not followed by "ref=" or "ref    ="
    )*+  # repeat the atomic group zero or more times.
    (?<type> href )
  | #### OR ####
    <form\s        # the form case
    (?> # possible content before the "action" attribute. (same principle)
        [^a>]++
      |
        \Ba++
      |
        a(?!ction\s*+=)
    )*+
    (?<type> action )
)
\s*+ = \s*+     # optional spaces before and after the "=" sign
\K              # resets all on the left from match result
(?<quote> ["']?+ )
(?<url> [^\s"'>]*+ )
\g{quote}       # backreference to the "quote" named capture (", ', empty)
~xi
LOD;

请注意,此模式只会匹配带有可能引号的 url。但是,如果需要,属性名称将存储在命名的捕获组“类型”中。

然后您可以将所有这些用于:

$html = preg_replace_callback($pattern,
    function ($m) {
        $url = $m['url'];
        $type = lowercase($m['type']);
        $quote = $m['quote'];
        // make what you want with the url, type and quotes
        return $quote . $url . $quote;        
    }, $html);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-07
    • 2013-02-21
    • 1970-01-01
    • 1970-01-01
    • 2013-04-18
    • 2021-08-05
    相关资源
    最近更新 更多