为什么匿名函数在下面的程序中没有将整个数组或字符串作为参数传递给它?

Why the anonymous function is not getting an entire array or string passed as an argument to it in following program?

考虑下面的工作代码:

<?php
  echo preg_replace_callback('~-([a-z])~', function ($match) {
    /*Below var_dump() outputs
       array(2) {
         [0]=>
         string(2) "-w"
         [1]=>
         string(1) "w"
       }
    var_dump($match);*/
    return strtoupper($match[1]);
  }, 'hello-world');
  // outputs helloWorld
?>

以上代码运行良好并生成了输出。但是我在理解它在匿名函数中的工作时遇到了一些问题。

我的问题是为什么匿名函数没有得到包含值 helloWorld 的整个数组或字符串?

为什么会得到下面这个奇怪的数组?

Array
(
  [0] => -w
  [1] => w
)

下面我来解释一下

你的 Regx '~-([a-z])~' 说:

  • - 文字,匹配 - 一次。
  • (..) 捕获组,return 比赛结果。
  • [a-z]字符集,匹配az一次。

回调的参数基于匹配项。您得到匹配 010 是 Regx 匹配的所有内容(包括 -)。 1first 捕获组中的所有内容。

所以当你给它 hello-world 时,匹配从 - 开始并在第一个 [a-z] 之后结束,或者在这种情况下是 w.

现在,如果您添加另一个捕获组,那么您将匹配 2。例如:

'~-([a-z])([a-z])~'

你会得到类似 [0=>'-wo', 1=>'w',2=>'o'] 的东西。

在此处在线测试:https://regex101.com/r/yakHNF/1

如果您要将其更改为

'~-([a-z]+)~'

它会给你 [0=>'-world', 1=>'world'],因为 + 匹配了一次或多次,所以它匹配了整个单词。

"fullstring match"(输出数组中的[0]元素)是不可避免的。您可以 避免(减少输出数组膨胀并提高正则表达式效率)的是使用捕获组。您需要匹配连字符和字母,并且只匹配 return 字母——这样连字符就被删除了。

这是没有输出数组膨胀的等效方法:(Demo)

echo preg_replace_callback('~-[a-z]~', function ($match) {
    /*Below var_export() outputs only the "fullstring" match (no capture groups)
        array (
            0 => '-w',
        )
    var_export($match); */
    return strtoupper($match[0][1]);  // return only the character at offset 1 (2nd char)
  }, 'hello-world');

输出:

helloWorld

我只是添加另一个(可能是多余的)答案,因为我认为您主要是误解了 anonymous/callback 函数的任务。 ➜ 它应该做的很少。

基本上这是逻辑流程:

  1. 您输入的字符串是'hello-world'

  2. 匹配 preg_replace_callback

  3. 并且正则表达式仅从中提取 '-w'

  4. 你的回调函数只接收那个匹配,分成 $match=["-w", "w"]
    (@mickmack 已经解释了原因)

  5. 匿名函数只适用于匹配的部分/用这段摘录做它的替换魔术。

    • 它永远不会工作,也不需要整个原始输入 (hello-world)。

    • 因为它只是将第二个单词的第一个字母大写,所以 $match[1] 就足够了。

    • 就这样而已returns'W'

    • 回调函数的工作不是对整个/原始字符串进行替换。

  6. preg_replace_callback 对输入字符串执行实际的替换任务

    • 它将正则表达式匹配的 '-w' 换成大写 'W',因为 从您的匿名函数返回

    • 正如@ArtisticPhoenix 所解释的那样,您可以更改正则表达式并进行匹配,然后让您的回调获得手头任务的"better view"。

但同样,对于实际目的,如果您的回调只看到一个字母并且只看到 returns 那个字母就足够了。