我错过了一些让我在使用递归(?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'选项,我将匹配两个$str的第一个FIND。
但是我怎样才能得到所有的呢?我试着使用'(?R)',但我真的不明白它是如何工作的。
谢谢。
编辑:真正的工作是找到<a>
&</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>
我的工作是使用regex将每个标题都大写(例如title="A LINK")。
我的最后一个模式是:
#<a .* title='"(.*)'".*</a>#Uis
让我抓住了(title="a link")和(title="and again")。你的方法应该工作(stribizhev),但我没有成功实现它,我仍然在它。
更新答案-更改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获取带有属性title
的<a>
元素(a
)。
我使用mb_strtoupper
假设你有UTF8输入。请进行相应的调整,或者如果您不打算使用Unicode,请使用strtoupper
。
更新前的原始答案
这是一个正则表达式,可以让您替换-start
和-end
中的所有FIND
子字符串:
(-start|(?!^)'G)(.*?)FIND(?=.*end-)
看到演示
用$1$2NEW_WORD
代替
$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-)
-仅当FIND
后面有文字字符串end-
时。
有关'G
运算符的更多信息,请参见'G何时在正则表达式中有用?
如果使用preg_replace_callback
,为什么不愿意使用.*?
呢?
$my_pattern = "/-start(.*?)end-/s";
$str = preg_replace_callback($my_pattern, function($matches) {
return str_replace("FIND", "<b>FIND</b>", $matches[0]);
}, $str1.$str2);
或者在回调中做其他事情。你想达到什么目标?