繁体   English   中英

使用 PHP preg_match_all() 匹配子串

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM