[英]Matching substrings with PHP preg_match_all()
我正在尝试创建一个轻量级的 BBCode 解析器,而不为每个元素硬编码正则表达式匹配。 我的方法是利用preg_replace_callback()
来处理 function 中的匹配。
我简单但令人沮丧的方法是使用正则表达式对元素名称进行分组,并使用每个 function 的开关进行不同的解析。
这是我的正则表达式模式:
'~\[([a-z]+)(?:=(.*))?(?: (.*))?\](.*)(?:\[/\1\])~siU'
这是我必须测试的preg_replace_callback()
。
return preg_replace_callback(
'~\[([a-z]+)(?:=(.*))?(?: (.*))?\](.*)(?:\[/\1\])~siU',
function($matches) {
var_dump($matches);
return "<".$matches[1].">".$matches[4]."</".$matches[1].">";
},
$this->raw
);
这个问题把我难住了。 正则表达式模式似乎不会递归匹配,这意味着如果它匹配一个元素,它就不会匹配其中的元素。
以这个 BBCode 为例:
[i]This is all italics along with a [b]bold[/b].[/i]
这只会匹配 [u],不会匹配其中的任何元素,所以看起来像
这都是斜体加上[b]粗体[/b]。
preg_match_all()
继续表明情况确实如此,我尝试过使用贪婪的语法和模式。
我该如何解决这个问题?
感谢@Casimir et Hippolyte 的评论,我能够像他们说的那样使用 while 循环和 count 参数来解决这个问题。
基本的正则表达式字符串不起作用,因为我想在[color=red]
或[img width=""]
等标签中使用值。
这是最终的代码。 它并不完美,但它有效。
$str = $this->raw;
do {
$str = preg_replace_callback(
'~\[([a-z]+)(?:=(.*))?(?: (.*?))?\](.*?)(?:\[/\1\])~si',
function($matches) {
return "<".$matches[1].">".$matches[4]."</".$matches[1].">";
},
$str,
-1,
$count
);
} while ($count != 0);
return $str;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.