PHP中递归正则表达式的语法

时间:2015-09-12 10:40:42

标签: php regex

我错过了一些让我无法使用递归(?R)的事情。

解释我的问题的一个例子'明确':

$str1 = "somes text -start bla bla FIND bla bla bla FIND bla FIND bla end-";
$str2 = "somes text -start bla bla FIND bla bla bla FIND bla FIND bla end-";
$my_pattern = "-start .*(FIND).* end-";

preg_replace_callback($my_pattern, 'callback', $str1.$str2);

它只匹配最后一个FIND。

' ungreedy'选项i匹配$ str的第一个FIND。

但我怎样才能得到所有这些?我试图使用'(?R)'但我真的不明白它是如何运作的。

感谢。

编辑:真正的工作是找到所有的标题&#39;财产<a>&amp; </a>。 我知道使用正则表达式解析html并不是优化,但它只是学校中的一项工作来学习正则表达式。

这就是为什么我没有把真正的工作,我想了解并能够自己做。

<html>
 <head><title>Nice page</title></head>
<body>
    Hello World
 <a href=http://cyan.com title="a link">
                this is a link
 </a>
<br />
<a href=http://www.riven.com> Here too <img src=wrong.image title="and again">
    <span>Even that<div title="same">all the same</div></span>
</a>
</body>
</html>

我的工作也是使用正则表达式将每个标题都用大写(标题=&#34; A LINK&#34;例如)。

我的最后一个模式是:

#<a .* title=\"(.*)\".*</a>#Uis

让我抓住(标题=&#34;链接&#34;)和(标题=&#34;再次&#34;)。你的方法应该工作(stribizhev),但我没有成功实现它,我还在它上面。

2 个答案:

答案 0 :(得分:1)

更新的答案 - 更改HTML格式的案例

您需要将DOMDocument与DOMXPath一起使用,以安全地获取所有标题属性并使用mb_strtoupper更改它们:

$html = "<<YOUR_HTML>>";
$dom = new DOMDocument('1.0', 'UTF-8');
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);

$xpath = new DOMXPath($dom);
$titles = $xpath->query('//a[@title]');

foreach($titles as $title) { 
   $title->setAttribute("title", mb_strtoupper($title->getAttribute("title"), 'UTF-8'));
}

echo $dom->saveHTML();

请参阅IDEONE demo

//a[@title] xpath获取<a>元素(a),其属性为title

假设您有UTF8输入,我使用mb_strtoupper。请相应调整,或​​者如果您不打算使用Unicode,只需使用strtoupper

更新前的原始答案

以下是一个正则表达式,可让您替换FIND-start中的所有-end子字符串:

(-start|(?!^)\G)(.*?)FIND(?=.*end-)

请参阅demo

替换为$1$2NEW_WORD

PHP code

$re = "#(-start|(?!^)\G)(.*?)FIND(?=.*end-)#"; 
$str = "somes text -start bla bla FIND bla bla bla FIND bla FIND bla end-"; 
$subst = "$1$2NEW_WORD"; 
$result = preg_replace($re, $subst, $str);
echo $result;

注意:如果您有多个start-end块,则很可能需要一个驯化的贪婪令牌(?:(?!-start|end-|FIND).)*而不是.*?.*

正则表达式分解:

  • (-start|(?!^)\G) - 此组包含两个选项:
    • -start - 匹配文字字符串-start
    • (?!^)\G - 在最后一次成功匹配后立即断言原始输入字符串中的位置。 \G也可以断言字符串的开头,但我们会将其排除在负面预测之外。
  • (.*?) - 匹配任意数量的字符,但尽可能少
  • FIND - 文字字符串FIND
  • (?=.*end-) - 仅在end-后面有文字字符串FIND

有关\G运算符的详细信息,请参阅When is \G useful application in a regex?What good is \G in a regular expression?

答案 1 :(得分:0)

如果使用preg_replace_callback,为什么reluctant .*?不方便。

$my_pattern = "/-start(.*?)end-/s";

$str = preg_replace_callback($my_pattern, function($matches) {
  return str_replace("FIND", "<b>FIND</b>", $matches[0]);
}, $str1.$str2);

或者在回调中做其他事情。你想要实现什么目标?