我对正则表达式很糟糕。我试图取代这个:
public static function camelize($word) {
return preg_replace('/(^|_)([a-z])/e', 'strtoupper("\\2")', $word);
}
使用带有匿名函数的preg_replace_callback。我不明白\\ 2是做什么的。或者就此而言preg_replace_callback的工作原理。
实现这一目标的正确代码是什么?
在正则表达式中,您可以使用(brackets)
“捕获”匹配字符串的一部分;在这种情况下,你正在捕捉比赛的(^|_)
和([a-z])
部分。这些编号从1开始编号,因此您有后引用1和2.匹配0是整个匹配的字符串。
/e
修饰符采用替换字符串,并用反斜杠替换后跟一个数字(例如\1
)和适当的反向引用 - 但因为你在一个字符串中,你需要转义反斜杠,所以你得到'\\1'
。然后(有效地)运行eval
来运行生成的字符串,好像它是PHP代码(这就是为什么它被弃用,因为它很容易以不安全的方式使用eval
)。
preg_replace_callback
函数接受一个回调函数,并传递一个包含匹配的反向引用的数组。那么你在哪里编写'\\1'
,而是访问该参数的元素1 - 例如如果你有一个function($matches) { ... }
形式的匿名函数,那么该函数内的第一个反向引用是$matches[1]
。
所以/e
的论点
'do_stuff(\\1) . "and" . do_stuff(\\2)'
可能成为回调
function($m) { return do_stuff($m[1]) . "and" . do_stuff($m[2]); }
或者在你的情况下
'strtoupper("\\2")'
可能成为
function($m) { return strtoupper($m[2]); }
请注意,$m
和$matches
不是魔术名称,它们只是我在声明我的回调函数时给出的参数名称。此外,您不必传递匿名函数,它可以是函数名称作为字符串,或者某种形式的array($object, $method)
,as with any callback in PHP,例如
function stuffy_callback($things) {
return do_stuff($things[1]) . "and" . do_stuff($things[2]);
}
$foo = preg_replace_callback('/([a-z]+) and ([a-z]+)/', 'stuffy_callback', 'fish and chips');
与任何函数一样,默认情况下,您无法访问回调之外的变量(来自周围的范围)。使用匿名函数时,可以使用use
关键字导入需要访问的变量as discussed in the PHP manual。例如如果旧的论点是
'do_stuff(\\1, $foo)'
然后新的回调可能看起来像
function($m) use ($foo) { return do_stuff($m[1], $foo); }
preg_replace_callback
而不是/e
修饰符,因此您需要从“模式”参数中删除该标志。因此像/blah(.*)blah/mei
这样的模式将成为/blah(.*)blah/mi
。/e
修饰符在参数内部使用了addslashes()
的变体,因此一些替换使用stripslashes()
来删除它;在大多数情况下,您可能希望从新回调中删除对stripslashes
的调用。