求高手解决正则递归匹配的问题!

powerpolly 2008-05-23 09:53:59
$str = '
其他文本其他文本<div>仅单层</div></div>(注意:后面多一个</div>)
其他文本其他文本其他文本
<div>外层
<div>中层
<div>内层</div>
</div>
</div>
其他文本<font>外层<span>里层</span></font>其他文本其他文本……
';
$re = ???
preg_match_all($re,$str,$matches);
print_r($matches[0]);
希望结果是:
array(
0 => <div>仅单层</div>
1 => <div>外层
<div>中层
<div>内层</div>
</div>
</div>
2 => <font>外层<span>里层</span></font>
)

往往出来的第一个匹配是:<div>仅单层</div></div>,这不是想要的 <div>仅单层</div>

国内介绍正则递归的资料很少。希望高手顺便解释一下递归用法。
...全文
325 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
powerpolly 2008-05-26
  • 打赏
  • 举报
回复
能否用来去掉UBB代码?

UBB代码经常可能有嵌套:

$str = '
[normal text here]加粗红色[color=#0000FF]蓝色红色[/color][/not match]
';


请问能否一次性去掉配对的UBB代码?

$re = ?
$result = preg_replace($re, $replace, $str);
print_r($result);

结果为:
[normal text here]加粗红色蓝色红色[/not match]
powerpolly 2008-05-26
  • 打赏
  • 举报
回复
ice_berg16,能否详细说明递归的用法?

$re = "#<[a-z]([^ >]+)[^<>]*>([^<>]*|(?R))*</[^<>]+>#is";

([^<>]*|(?R))* 这里没看懂。
SysTem128 2008-05-25
  • 打赏
  • 举报
回复

<?php
$str = '
其他文本其他文本 <div>仅单层 </div> </div>(注意:后面多一个 </div>)
其他文本其他文本其他文本
<div>外层
<div>中层
<div>内层 </div>
</div>
</div>
# 这是另一种情况
# start 闭合错误
<div>外层
<div>中层
<div>内层 </div>
</div>
</font>
# end 闭合错误
其他文本 <font>外层 <span>里层 </span> </font>其他文本其他文本……
';
$re = "/<([a-z]+)[^>]*>([^<>]|(?R))*<\/\\1>/is";
preg_match_all($re,$str,$matches);
print_r($matches[0]);
echo PHP_VERSION; // 5.2.5
?>



嘿嘿~被抢先了一步,整理一下~套点分~
fxs_2008 2008-05-25
  • 打赏
  • 举报
回复
楼主查一下手册吧!Perl正则规范里有一段说明!仔细看一下!
ice_berg16很强大!
fxs_2008 2008-05-25
  • 打赏
  • 举报
回复
ice_berg16 的很强大,收藏学习了!可以解决很多问题

查了一下,
$re = "`class[^{]+(\{([^{}]* ¦(?1))*\})`s";
也是ice_berg16 写的,

class[^{]+ 以class开始,后跟非{一个或多个

(\{([^{}]* ¦(?1))*\})分组
\{([^{}]* ¦(?1))*\} 匹配{}以内容
([^{}]* ¦(?1))* 中的内容,并递归,这具看不明白,不知为何要用(?1),这个指的递归哪个,第一个分组捕获?另外(?1)*后面有个*也不明白有什么用

手册上只有一小段英文介绍










ice_berg16 2008-05-24
  • 打赏
  • 举报
回复
<?php
//*
$str = '
其他文本其他文本 <div>仅单层 </div> </div>(注意:后面多一个 </div>)
其他文本其他文本其他文本
<div>外层
<div>中层
<div>内层 </div>
</div>
</div>
其他文本 <font>外层 <span>里层 </span> </font>其他文本其他文本……
';
$re = "#<[a-z]([^ >]+)[^<>]*>([^<>]*|(?R))*</[^<>]+>#is";
//*/

preg_match_all($re,$str,$matches);
print_r($matches[0]);
?>
fxs_2008 2008-05-23
  • 打赏
  • 举报
回复
不用递归;
二次匹配即可
第一匹配整体;
对每个匹配第二次从整体再匹配各个部分

powerpolly 2008-05-23
  • 打赏
  • 举报
回复

其实就是正则递归,比如(?1),表示递归引用第一个括号的内容。我大概知道,但还是写不好。

搜索老帖,找到一位高人写的如下正则,作用是匹配一个*.php文件中的每个类class的内容。

$re = "`class[^{]+(\{([^{}]*|(?1))*\})`s";

谁能分析一下用法?

21,886

社区成员

发帖
与我相关
我的任务
社区描述
从PHP安装配置,PHP入门,PHP基础到PHP应用
社区管理员
  • 基础编程社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧