PHP 正则表达式:如何在函数中使用捕获的组
PHP regex : How to use captured groups in a function
我正在 php 中构建一个手工制作的功能,用于搜索特定标签([b][/b] 用于粗体,[i][/i] 用于斜体,[img][ /img] 为图片)在一个字符串中,将它们替换为它们的 html 等价物。在替换之前,我还必须在单独的函数中处理 [img] [/img] 标签(字符串中可以有多个)之间的内容,我在这里称之为 foo :
<?php
function convert($txt){
$patterns = array( '/\[b\](.*?)\[\/b\]/' ,
'/\[i\](.*?)\[\/i\]/' ,
'/\[img\](.*?)\[\/img\]/');
$replace = array("<b></b>" , "<i></i>" , foo("") );
$res = preg_replace($patterns,$replace, $txt);
return $res;
}
它适用于 b 和 i 标签,但不适用于 img。
这里的问题是: 当我将捕获的组(我认为由“$1”引用)放入函数中时,它将“$1”视为字符串,并且不是它引用的内容。
例如,如果 foo 声明如下:
function foo($var){
echo $var;
}
如果我将字符串 text1 [img]path[/img] text2
放入 convert()
然后 ""
将被回显,而不是 "path"
因此这是我的问题: 我如何“评估”我在不同函数中捕获的字符串。在前面的示例中,要在 foo 中回显 [img][/img] 标签之间的内容是什么?
感谢大家花时间回复。
可以先抓取字符串再运行函数:
<?php
function convert($txt){
preg_match('/\[img\](.*?)\[\/img\]/', $txt, $match);
$patterns = array( '/\[b\](.*?)\[\/b\]/' ,
'/\[i\](.*?)\[\/i\]/' ,
'/\[img\](.*?)\[\/img\]/');
$replace = array("<b></b>" , "<i></i>" , foo($match[1]) );
$res = preg_replace($patterns,$replace, $txt);
return $res;
}
试试这个
<?php
function convert($txt){
$pattern = array('/\[b\](.*?)\[\/b\]/' => function($matches) { return "
<b>$matches[1]</b>"; },
'/\[i\](.*?)\[\/i\]/' => function($matches) { return "
<i>$matches[1]</i>"; },
'/\[img\](.*?)\[\/img\]/' => function($matches) { echo
$matches[1]; return "<img>$matches[1]</img>"; });
$res = preg_replace_callback_array($pattern, $txt);
return $res;
}
$result = convert("text1 [img]path[/img] text2");
echo "\n$result\n";
输出:
path
text1 <img>path</img> text2
首先,强烈建议使用合法的 BBCode 解析器(库)而不是正则表达式方法。 custom-developed 解析器应该比基本的正则表达式模式更好地处理边缘情况。
既然给出了免责声明,解决从 preg_replace()
的替换参数调用函数的问题的方法是调用 preg_replace_callback()
,或者在您的情况下,也许更好地编码为preg_replace_callback_array()
因为您正在为不同的模式寻求不同的回调。
代码:(Demo)
function convert(string $txt): string {
do {
$txt = preg_replace_callback_array(
[
'~\[([bi])](.*?)\[/]~' => fn($m) => sprintf('<%1$s>%2$s</%1$s>', $m[1], $m[2]),
'~\[img](.*?)\[/img]~' => 'foo',
],
$txt,
-1,
$count
);
} while ($count);
return $txt;
}
function foo(array $m): string {
return '<img src="' . $m[1] . '">';
}
echo convert("text1 [img]path/src[/img] text2 [b]bold [i]nested string[/i][/b] [img]another/path/to/file[/img] [b]nice[/b] lingering end bbtag [/b] and [b]unclosed");
输出:
text1 <img src="path/src"> text2 <b>bold <i>nested string</i></b> <img src="another/path/to/file"> <b>nice</b> lingering end bbtag [/b] and [b]unclosed
您会注意到调用 foo()
是通过使用其字符串名称作为回调值来完成的。尽管未在 'foo'
值中明确提及,但 matches 数组已发送到自定义函数。
我在 do-while()
循环中调用 preg_replace_callback_array()
以确保替换嵌套的 bbcode 标签(否则会被忽略,因为它们的父标签完全包围了它们)。
如果您希望处理 [u]
标签,只需在第一个正则表达式模式中的 bi
之后添加 u
。
我正在 php 中构建一个手工制作的功能,用于搜索特定标签([b][/b] 用于粗体,[i][/i] 用于斜体,[img][ /img] 为图片)在一个字符串中,将它们替换为它们的 html 等价物。在替换之前,我还必须在单独的函数中处理 [img] [/img] 标签(字符串中可以有多个)之间的内容,我在这里称之为 foo :
<?php
function convert($txt){
$patterns = array( '/\[b\](.*?)\[\/b\]/' ,
'/\[i\](.*?)\[\/i\]/' ,
'/\[img\](.*?)\[\/img\]/');
$replace = array("<b></b>" , "<i></i>" , foo("") );
$res = preg_replace($patterns,$replace, $txt);
return $res;
}
它适用于 b 和 i 标签,但不适用于 img。
这里的问题是: 当我将捕获的组(我认为由“$1”引用)放入函数中时,它将“$1”视为字符串,并且不是它引用的内容。 例如,如果 foo 声明如下:
function foo($var){
echo $var;
}
如果我将字符串 text1 [img]path[/img] text2
放入 convert()
然后 ""
将被回显,而不是 "path"
因此这是我的问题: 我如何“评估”我在不同函数中捕获的字符串。在前面的示例中,要在 foo 中回显 [img][/img] 标签之间的内容是什么?
感谢大家花时间回复。
可以先抓取字符串再运行函数:
<?php
function convert($txt){
preg_match('/\[img\](.*?)\[\/img\]/', $txt, $match);
$patterns = array( '/\[b\](.*?)\[\/b\]/' ,
'/\[i\](.*?)\[\/i\]/' ,
'/\[img\](.*?)\[\/img\]/');
$replace = array("<b></b>" , "<i></i>" , foo($match[1]) );
$res = preg_replace($patterns,$replace, $txt);
return $res;
}
试试这个
<?php
function convert($txt){
$pattern = array('/\[b\](.*?)\[\/b\]/' => function($matches) { return "
<b>$matches[1]</b>"; },
'/\[i\](.*?)\[\/i\]/' => function($matches) { return "
<i>$matches[1]</i>"; },
'/\[img\](.*?)\[\/img\]/' => function($matches) { echo
$matches[1]; return "<img>$matches[1]</img>"; });
$res = preg_replace_callback_array($pattern, $txt);
return $res;
}
$result = convert("text1 [img]path[/img] text2");
echo "\n$result\n";
输出:
path
text1 <img>path</img> text2
首先,强烈建议使用合法的 BBCode 解析器(库)而不是正则表达式方法。 custom-developed 解析器应该比基本的正则表达式模式更好地处理边缘情况。
既然给出了免责声明,解决从 preg_replace()
的替换参数调用函数的问题的方法是调用 preg_replace_callback()
,或者在您的情况下,也许更好地编码为preg_replace_callback_array()
因为您正在为不同的模式寻求不同的回调。
代码:(Demo)
function convert(string $txt): string {
do {
$txt = preg_replace_callback_array(
[
'~\[([bi])](.*?)\[/]~' => fn($m) => sprintf('<%1$s>%2$s</%1$s>', $m[1], $m[2]),
'~\[img](.*?)\[/img]~' => 'foo',
],
$txt,
-1,
$count
);
} while ($count);
return $txt;
}
function foo(array $m): string {
return '<img src="' . $m[1] . '">';
}
echo convert("text1 [img]path/src[/img] text2 [b]bold [i]nested string[/i][/b] [img]another/path/to/file[/img] [b]nice[/b] lingering end bbtag [/b] and [b]unclosed");
输出:
text1 <img src="path/src"> text2 <b>bold <i>nested string</i></b> <img src="another/path/to/file"> <b>nice</b> lingering end bbtag [/b] and [b]unclosed
您会注意到调用 foo()
是通过使用其字符串名称作为回调值来完成的。尽管未在 'foo'
值中明确提及,但 matches 数组已发送到自定义函数。
我在 do-while()
循环中调用 preg_replace_callback_array()
以确保替换嵌套的 bbcode 标签(否则会被忽略,因为它们的父标签完全包围了它们)。
如果您希望处理 [u]
标签,只需在第一个正则表达式模式中的 bi
之后添加 u
。