草庐IT

PHP 理解回调——preg_replace_callback() 和 preg_match_all() 的区别

coder 2024-04-25 原文

我对 preg_replace_callback() 的使用有点困惑

我有一个 $content,里面有一些 URL。

我以前用过

 $content = preg_match_all( '/(http[s]?:[^\s]*)/i', $content, $links );


 foreach ($links[1] as $link ) {
            // we have the link. find image , download, replace the content with image
            // echo '</br>LINK : '. $link;
            $url = esc_url_raw( $link );
            $url_name = parse_url($url); 
            $url_name = $description = $url_name['host'];// get rid of http://..
            $url = 'http://somescriptonsite/v1/' .  urlencode($url)   . '?w=' . $width ;
            } 

    return $url;

但我真正需要的是用我解析的 URL 替换原始 URL...

所以我尝试了 preg_replace_callback:

function o99_simple_parse($content){

$content = preg_replace_callback( '/(http[s]?:[^\s]*)/i', 'o99_simple_callback', $content );


return $content;
}

和:

function o99_simple_callback($url){
    // how to get the URL which is actually the match? and width ??
        $url = esc_url_raw( $link );
        $url_name = parse_url($url); 
        $url_name = $description = $url_name['host'];// get rid of http://..
        $url = 'http://something' .  urlencode($url)   . '?w=' . $width ; 
        return $url; // what i really need to replace 
    }

我假设回调的工作方式是每次匹配都会调用回调(递归?)并取回结果,从而允许用解析后的 即时替换 $content 中的 URLS来自 o99_simple_callbac() 的 $url

但另一个question这里(尤其是 this comment)引发了我的怀疑。

如果 preg_replace_callback() 实际上传递了整个匹配数组,那么我之前使用的(第一个示例中的 preg_match_all())和回调示例 ?

我错过了什么/误解了什么?? 将 $content 中找到的 URL 替换为已解析的 url 的正确方法是什么?

最佳答案

其他答案可能已经足够了,但让我用一个更简单的例子再给你一个答案。

假设我们在 $subject 中有以下数据,

RECORD Male 1987-11-29 New York
RECORD Female 1987-07-13 Tennessee
RECORD Female 1990-04-14 New York

以及$pattern中的正则表达式,

/RECORD (Male|Female) (\d\d\d\d)-(\d\d)-(\d\d) ([\w ]+)/

让我们比较一下三种方法。

preg_match_all

首先, Vanilla preg_match_all:

preg_match_all($pattern, $subject, $matches);

$matches 结果如下:

Array
(
    [0] => Array
        (
            [0] => RECORD Male 1987-11-29 New York
            [1] => RECORD Female 1987-07-13 Tennessee
            [2] => RECORD Female 1990-04-14 New York
        )

    [1] => Array
        (
            [0] => Male
            [1] => Female
            [2] => Female
        )

    [2] => Array
        (
            [0] => 1987
            [1] => 1987
            [2] => 1990
        )

    [3] => Array
        (
            [0] => 11
            [1] => 07
            [2] => 04
        )

    [4] => Array
        (
            [0] => 29
            [1] => 13
            [2] => 14
        )

    [5] => Array
        (
            [0] => New York
            [1] => Tennessee
            [2] => New York
        )

)

无论我们是在讨论我的示例中的性别字段还是您的示例中的 URL 字段,很明显,遍历 $matches[1] 只是遍历 那个领域:

foreach ($matches[1] as $match)
{
    $gender = $match;
    // ...
}

但是,如您所见,您对 $matches[1] 所做的更改,即使您通过引用遍历其子数组,也不会反射(reflect)在 中$subject您不能通过preg_match_all 执行替换。

preg_match_all 与 PREG_SET_ORDER

不过,在我们进入 preg_replace_callback 之前,让我们看一下 preg_match_all 的常用标志之一,PREG_SET_ORDER

preg_match_all($pattern, $subject, $matches, PREG_SET_ORDER);

这会输出一些(看似)完全不同的东西!

Array
(
    [0] => Array
        (
            [0] => RECORD Male 1987-11-29 New York
            [1] => Male
            [2] => 1987
            [3] => 11
            [4] => 29
            [5] => New York
        )

    [1] => Array
        (
            [0] => RECORD Female 1987-07-13 Tennessee
            [1] => Female
            [2] => 1987
            [3] => 07
            [4] => 13
            [5] => Tennessee
        )

    [2] => Array
        (
            [0] => RECORD Female 1990-04-14 New York
            [1] => Female
            [2] => 1990
            [3] => 04
            [4] => 14
            [5] => New York
        )

)

现在,每个子数组包含集合的捕获组每个匹配,而不是匹配的集合,每个捕获组。 (换句话说,这是另一个数组的转置。)如果您想使用每个匹配项的性别(或 URL),您现在必须这样写:

foreach ($matches as $match)
{
    $gender = $match[1];
    // ...
}

preg_replace_callback

这就是 preg_replace_callback 的样子。它为每个匹配集调用回调(即,一次包括所有捕获组),就像您使用PREG_SET_ORDER 旗帜。即对比preg_replace_callback的使用方式,

preg_replace_callback($pattern, $subject, 'my_callback');
function my_callback($matches)
{
    $gender = $match[1];
    // ...
    return $gender;
}

PREG_SET_ORDER 示例。请注意这两个示例如何以完全相同的方式遍历匹配项,唯一的区别是 preg_replace_callback 为您提供了返回替换值的机会。

关于PHP 理解回调——preg_replace_callback() 和 preg_match_all() 的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15673445/

有关PHP 理解回调——preg_replace_callback() 和 preg_match_all() 的区别的更多相关文章

  1. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  2. ruby - 如何在 Rails 4 中使用表单对象之前的验证回调? - 2

    我有一个服务模型/表及其注册表。在表单中,我几乎拥有服务的所有字段,但我想在验证服务对象之前自动设置其中一些值。示例:--服务Controller#创建Action:defcreate@service=Service.new@service_form=ServiceFormObject.new(@service)@service_form.validate(params[:service_form_object])and@service_form.saverespond_with(@service_form,location:admin_services_path)end在验证@ser

  3. ruby - 有人可以帮助解释类创建的 post_initialize 回调吗 (Sandi Metz) - 2

    我正在阅读SandiMetz的POODR,并且遇到了一个我不太了解的编码原则。这是代码:classBicycleattr_reader:size,:chain,:tire_sizedefinitialize(args={})@size=args[:size]||1@chain=args[:chain]||2@tire_size=args[:tire_size]||3post_initialize(args)endendclassMountainBike此代码将为其各自的属性输出1,2,3,4,5。我不明白的是查找方法。当一辆山地自行车被实例化时,因为它没有自己的initialize方法

  4. CAN协议的学习与理解 - 2

    最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总

  5. TimeSformer:抛弃CNN的Transformer视频理解框架 - 2

    Transformers开始在视频识别领域的“猪突猛进”,各种改进和魔改层出不穷。由此作者将开启VideoTransformer系列的讲解,本篇主要介绍了FBAI团队的TimeSformer,这也是第一篇使用纯Transformer结构在视频识别上的文章。如果觉得有用,就请点赞、收藏、关注!paper:https://arxiv.org/abs/2102.05095code(offical):https://github.com/facebookresearch/TimeSformeraccept:ICML2021author:FacebookAI一、前言Transformers(VIT)在图

  6. ruby-on-rails - ActiveRecord destroy_all - 2

    在Rails4.1中,ActiveRecorddestroy_all是否将整个函数包装在一个事务中?例如,如果我有一堆记录,我对其执行了destroy_all操作,它们对这些单独的对象运行了一些回调,其中一个失败了,整个操作会在那个时候回滚吗? 最佳答案 看起来不像:#Fileactiverecord/lib/active_record/relation.rb,line386defdestroy_all(conditions=nil)ifconditionswhere(conditions).destroy_allelseto_a.

  7. ruby - 易于初学者理解的 Ruby 库 - 2

    关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。关闭3年前。Improvethisquestion我正处于学习Ruby的阶段,我想查看一些小型库的源代码以了解它们是如何构建的。我不知道什么是小型图书馆,但希望SO能推荐一些易于理解的图书馆来学习。因此,如果有人知道一两个非常小的库,这是新手Rubyists学习的好例子,请推荐!我想使用Manveru'sInnatelib,因为它试图保持在2000LOC以下,但我还不熟悉其中经常使用的Ruby速记。也许大约100-5

  8. ruby - 无法理解 `puts{}.class` 和 `puts({}.class)` 之间的区别 - 2

    由于匿名block和散列block看起来大致相同。我正在玩它。我做了一些严肃的观察,如下所示:{}.class#=>Hash好的,这很酷。空block被视为Hash。print{}.class#=>NilClassputs{}.class#=>NilClass为什么上面的代码和NilClass一样,下面的代码又显示了Hash?puts({}.class)#Hash#=>nilprint({}.class)#Hash=>nil谁能帮我理解上面发生了什么?我完全不同意@Lindydancer的观点你如何解释下面几行:print{}.class#NilClassprint[].class#A

  9. ruby-on-rails - 将保存回调添加到单个 ActiveRecord 实例,可以吗? - 2

    是否可以为单个ActiveRecord实例添加回调?作为进一步的限制,这是继续使用库,所以我无法控制该类(除了对其进行猴子修补)。这或多或少是我想做的:defdo_something_creazymessage=Message.newmessage.on_save_call:do_even_more_crazy_stuffenddefdo_even_more_crazy_stuff(message)puts"Message#{message}hasbeensaved!Hallelujah!"end 最佳答案 你可以通过在创建对象后立

  10. ruby 正则表达式 : replace double slashes in URL - 2

    除了协议(protocol)定义中的斜杠('http[s]://'、'ftp://'等)之外,我想替换URL中的所有多个斜杠。我该怎么做?此代码无一异常(exception)地替换:url.gsub(/\/\/+/,'/') 最佳答案 您只需排除任何以:开头的匹配项url.gsub(/([^:])\/\//,'\1/') 关于ruby正则表达式:replacedoubleslashesinURL,我们在StackOverflow上找到一个类似的问题: http

随机推荐