PHP正则表达式:如何在函数中使用捕获的组



我正在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>$1</b>" , "<i>$1</i>" , foo("$1") );
$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()

则回显"$1",而不是"path"


所以这是我的问题:它如何"评估"?我在另一个函数中捕获的字符串。在前面的例子中,要在foo中回显[img][/img]标记之间是什么?

感谢大家抽出时间来回复。

首先,强烈建议使用合法的BBCode解析器(库)而不是regex方法。自定义开发的解析器应该比基本的regex模式更好地处理边缘情况。

现在给出了免责声明,解决从preg_replace()的替换参数调用函数的问题的方法是调用preg_replace_callback(),或者在您的情况下,也许通过preg_replace_callback_array()更好地编码,因为您正在为不同的模式寻求不同的回调。

代码(演示):

function convert(string $txt): string {
do {
$txt = preg_replace_callback_array(
[
'~[([bi])](.*?)[/1]~' => 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]标记,只需在第一个regex模式的bi之后添加u

试试这个

<?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$resultn";

输出:

path
text1 <img>path</img> text2

您可以先获取字符串,然后运行函数:

<?php
function convert($txt){
preg_match('/[img](.*?)[/img]/', $txt, $match);
$patterns = array(  '/[b](.*?)[/b]/' ,
'/[i](.*?)[/i]/' ,
'/[img](.*?)[/img]/');
$replace = array("<b>$1</b>" , "<i>$1</i>" , foo($match[1]) );
$res = preg_replace($patterns,$replace, $txt);
return $res;
}