用 PHP preg_match_all() 匹配子字符串
Matching substrings with PHP preg_match_all()
我正在尝试创建一个轻量级的 BBCode 解析器,而无需为每个元素硬编码正则表达式匹配。我的方法是利用preg_replace_callback()
来处理函数中的匹配。
我的简单但令人沮丧的方法是使用正则表达式对元素名称进行分组,并使用每个函数的开关进行不同的解析。
这是我的正则表达式模式:
'~\[([a-z]+)(?:=(.*))?(?: (.*))?\](.*)(?:\[/\])~siU'
这是我要测试的 preg_replace_callback()
。
return preg_replace_callback(
'~\[([a-z]+)(?:=(.*))?(?: (.*))?\](.*)(?:\[/\])~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],不会匹配其中的任何元素,因此看起来像
This is all italics along with a [b]bold[/b].
preg_match_all()
继续表明情况确实如此,我已经尝试搞乱贪婪的语法和模式。
我该如何解决这个问题?
感谢@Casimir et Hippolyte 的评论,我能够像他们说的那样使用 while 循环和计数参数解决这个问题。
基本的正则表达式字符串不起作用,因为我想在 [color=red]
或 [img width=""]
.
等标签中使用值
这是最终的代码。它并不完美,但它确实有效。
$str = $this->raw;
do {
$str = preg_replace_callback(
'~\[([a-z]+)(?:=([^]\s]*))?(?: ([^[]*))?\](.*?)(?:\[/\])~si',
function($matches) {
return "<".$matches[1].">".$matches[4]."</".$matches[1].">";
},
$str,
-1,
$count
);
} while ($count);
return $str;
我正在尝试创建一个轻量级的 BBCode 解析器,而无需为每个元素硬编码正则表达式匹配。我的方法是利用preg_replace_callback()
来处理函数中的匹配。
我的简单但令人沮丧的方法是使用正则表达式对元素名称进行分组,并使用每个函数的开关进行不同的解析。
这是我的正则表达式模式:
'~\[([a-z]+)(?:=(.*))?(?: (.*))?\](.*)(?:\[/\])~siU'
这是我要测试的 preg_replace_callback()
。
return preg_replace_callback(
'~\[([a-z]+)(?:=(.*))?(?: (.*))?\](.*)(?:\[/\])~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],不会匹配其中的任何元素,因此看起来像
This is all italics along with a [b]bold[/b].
preg_match_all()
继续表明情况确实如此,我已经尝试搞乱贪婪的语法和模式。
我该如何解决这个问题?
感谢@Casimir et Hippolyte 的评论,我能够像他们说的那样使用 while 循环和计数参数解决这个问题。
基本的正则表达式字符串不起作用,因为我想在 [color=red]
或 [img width=""]
.
这是最终的代码。它并不完美,但它确实有效。
$str = $this->raw;
do {
$str = preg_replace_callback(
'~\[([a-z]+)(?:=([^]\s]*))?(?: ([^[]*))?\](.*?)(?:\[/\])~si',
function($matches) {
return "<".$matches[1].">".$matches[4]."</".$matches[1].">";
},
$str,
-1,
$count
);
} while ($count);
return $str;