正则表达式替换 preg_replace 基础入门应用 2
发布时间:2012年9月27日 更新时间:2024年6月3日
作者:未知 文章ID:5945 浏览:
作者:未知 文章ID:5945 浏览:
有时候,我们需面对一种特殊的情况,请看下例:
$str="a2b333a56b33b";
echo preg_replace("/a.*b/","",$str); //本来是想替换 a2b 和a56b的,但输出结果却是空白
想一下,为什么上例输出结果是空白呢? 因為整个字符串是以a 开头,以b结尾。所以把整个字符串都替换了。
当一个表达式既符合短字符串的匹配,又符合长字符串的匹配,正则表达式在默认情况,是匹配最长的那个,这种情况叫做正则表达式贪婪匹配。
即匹配尽量多的字符。
加深一下理解,再试下下面几个例:
$str="abb3";
echo preg_replace("/a.*b/","",$str); //输出3 , 按照贪婪匹配的原则, a.*b 匹配的是abb,而不是ab
$str="aabb5"; //嵌套的情况,
echo preg_replace("/a.*b/","",$str); // 输出5,按照贪婪匹配的原则, a.*b 匹配的是aabb,而不是中间的ab
可能这时候你会问,如果我真想替换是中间的ab字符,而不想替换aabb呢,那么你又需要学习:懒惰匹配
$str="5abb5";
echo preg_replace("/a.*?b/","",$str); //输出5b5 , *?表示匹配任意的次,但尽量少, 所以只替换5abb5中的ab,而不是abb
$str="5a1b22b5";
echo preg_replace("/a.*?b/","",$str); //输出 522b5 *?匹配最少的那个 a1b,而不是 a1b22b
注意:懒惰匹配是指嵌套情况下的最少重复。
请看下例:
$str="5a1ba22b5";
echo preg_replace("/a.*?b/","",$str); //输出结果是55, a1b 和a22b并不是嵌套关系,所以这个不能用懒惰匹配来解释,此例可以看作是替换了a1b和a22b。
总结一下:贪婪匹配匹配尽量多的字符,懒惰匹配匹配尽量少的字符
懒惰匹配还有其它的表达方式:
*? 重复任意次,但尽可能少重复
+? 重复1次以上,但尽可能少重复
?? 重复0次或1次,但尽量少重复
{n,m}? 重复n到m次,但尽量少重复
{n,}? 重复n次以上,但尽量少重
懒惰匹配还有个特殊的情况:
$str="aabab";
echo preg_replace("/a.*?b/","",$str); //此时输出的结果是空白
为什么上例中a.*?b 替换了整个字符串? 其实,并不是因为替换了整个字符串,而是 替换了aab 和ab
实战篇
去掉所有HTML标识
假如你有一份HTML
<html>
<head>
<title></title>
</head>
<body>
<font color="#ff0000">PHP正则表达式</font>
<a class='a1' href="">Click Here</a>
</body>
</html>
当你用PHP的 file_get_contents 把它全部读入了 一个字符串 $str之后。
如果你只需要这份文件里面的文字,不要其它HTML标记。如何去掉呢?
先分析一下,不管什么HTML标记,都有个特点:以<开头,以> 结尾,我们只需要去掉以<开头,以> 结尾的字符即可
可能你会想到用以下的表达式
$str= preg_replace("/<.*>/","",$str); // 这样可不行。为什么?试验一下,看下例:
$str="111<div>333</div>88";
echo preg_replace("/<.*>/","",$str); //结果输出 11188, 它把333也去掉了,我们只想去掉<div></div>标记,但根据贪婪匹配的原理,这个表达式会去 掉:<div>333</div>
那么,我们改为使用懒惰匹配
$str="111<div>333</div>88";
echo preg_replace("/<.*?>/","",$str); //结果输出:11133388 正是我们想要的结果
有时候,HTML标记常会出现嵌套的现象:
$str="111<div>3<div>444</div>33</div>88";
echo preg_replace("/<.*?>/","",$str); //结果输出:11134443388 也是我们想要的结果
去掉超级链接
如果我们并不想去掉超级链接,而是想去掉超级链接标识呢?
先分析一下超链接标识的特点, <a href="aa.php">Click Herer</a>
还可能有 <a class="a1" href="aa.php">Click Here</a> 或 <a class="a1" href="aa.php" target=_blank >Click Here</a>
还可能有大小写不同的情况 <A HREF="aa.php">Click Herer</a>
不管什么情况, 肯定是 <a 开头 里面含有 href字眼
$str="111<a href=''></a>88";
echo preg_replace("/<a href=''>/i","",$str); //这样输出的结果是111</a>88 ,而没有去掉</a>
改进一下:
$str="111<a href=''></a>88";
echo preg_replace("/<a href=''>|<\/a>/i","",$str); // </a>要用<\/a>表示,加斜杠表转义,否则会出错的, 加i是为了不区分大小写
上例中输出了11188 ,是正确去掉超链接标识了,但上例的表达式壮健性太差了,稍有变化,就会出错。
稍变一下:
$str="111<a href=''></a>88"; // 如果href 前面多几个空格
echo preg_replace("/<a href=''>|<\/a>/i","",$str); //输出111<a href=''>88, 这样就出错了。
因此我们再将其改进一下:
$str="111<a href=''></a>88";
echo preg_replace("/<a href=''>|<\/a>/i","",$str);
作业题:
下面是一条壮健性比较好的替换超链接代码的表达式, 好好分析一下
echo preg_replace("/<a\s+href=[^>]*>|<\/[^a]*a[^>]*>/i","",$str);
$str="a2b333a56b33b";
echo preg_replace("/a.*b/","",$str); //本来是想替换 a2b 和a56b的,但输出结果却是空白
想一下,为什么上例输出结果是空白呢? 因為整个字符串是以a 开头,以b结尾。所以把整个字符串都替换了。
当一个表达式既符合短字符串的匹配,又符合长字符串的匹配,正则表达式在默认情况,是匹配最长的那个,这种情况叫做正则表达式贪婪匹配。
即匹配尽量多的字符。
加深一下理解,再试下下面几个例:
$str="abb3";
echo preg_replace("/a.*b/","",$str); //输出3 , 按照贪婪匹配的原则, a.*b 匹配的是abb,而不是ab
$str="aabb5"; //嵌套的情况,
echo preg_replace("/a.*b/","",$str); // 输出5,按照贪婪匹配的原则, a.*b 匹配的是aabb,而不是中间的ab
可能这时候你会问,如果我真想替换是中间的ab字符,而不想替换aabb呢,那么你又需要学习:懒惰匹配
$str="5abb5";
echo preg_replace("/a.*?b/","",$str); //输出5b5 , *?表示匹配任意的次,但尽量少, 所以只替换5abb5中的ab,而不是abb
$str="5a1b22b5";
echo preg_replace("/a.*?b/","",$str); //输出 522b5 *?匹配最少的那个 a1b,而不是 a1b22b
注意:懒惰匹配是指嵌套情况下的最少重复。
请看下例:
$str="5a1ba22b5";
echo preg_replace("/a.*?b/","",$str); //输出结果是55, a1b 和a22b并不是嵌套关系,所以这个不能用懒惰匹配来解释,此例可以看作是替换了a1b和a22b。
总结一下:贪婪匹配匹配尽量多的字符,懒惰匹配匹配尽量少的字符
懒惰匹配还有其它的表达方式:
*? 重复任意次,但尽可能少重复
+? 重复1次以上,但尽可能少重复
?? 重复0次或1次,但尽量少重复
{n,m}? 重复n到m次,但尽量少重复
{n,}? 重复n次以上,但尽量少重
懒惰匹配还有个特殊的情况:
$str="aabab";
echo preg_replace("/a.*?b/","",$str); //此时输出的结果是空白
为什么上例中a.*?b 替换了整个字符串? 其实,并不是因为替换了整个字符串,而是 替换了aab 和ab
实战篇
去掉所有HTML标识
假如你有一份HTML
<html>
<head>
<title></title>
</head>
<body>
<font color="#ff0000">PHP正则表达式</font>
<a class='a1' href="">Click Here</a>
</body>
</html>
当你用PHP的 file_get_contents 把它全部读入了 一个字符串 $str之后。
如果你只需要这份文件里面的文字,不要其它HTML标记。如何去掉呢?
先分析一下,不管什么HTML标记,都有个特点:以<开头,以> 结尾,我们只需要去掉以<开头,以> 结尾的字符即可
可能你会想到用以下的表达式
$str= preg_replace("/<.*>/","",$str); // 这样可不行。为什么?试验一下,看下例:
$str="111<div>333</div>88";
echo preg_replace("/<.*>/","",$str); //结果输出 11188, 它把333也去掉了,我们只想去掉<div></div>标记,但根据贪婪匹配的原理,这个表达式会去 掉:<div>333</div>
那么,我们改为使用懒惰匹配
$str="111<div>333</div>88";
echo preg_replace("/<.*?>/","",$str); //结果输出:11133388 正是我们想要的结果
有时候,HTML标记常会出现嵌套的现象:
$str="111<div>3<div>444</div>33</div>88";
echo preg_replace("/<.*?>/","",$str); //结果输出:11134443388 也是我们想要的结果
去掉超级链接
如果我们并不想去掉超级链接,而是想去掉超级链接标识呢?
先分析一下超链接标识的特点, <a href="aa.php">Click Herer</a>
还可能有 <a class="a1" href="aa.php">Click Here</a> 或 <a class="a1" href="aa.php" target=_blank >Click Here</a>
还可能有大小写不同的情况 <A HREF="aa.php">Click Herer</a>
不管什么情况, 肯定是 <a 开头 里面含有 href字眼
$str="111<a href=''></a>88";
echo preg_replace("/<a href=''>/i","",$str); //这样输出的结果是111</a>88 ,而没有去掉</a>
改进一下:
$str="111<a href=''></a>88";
echo preg_replace("/<a href=''>|<\/a>/i","",$str); // </a>要用<\/a>表示,加斜杠表转义,否则会出错的, 加i是为了不区分大小写
上例中输出了11188 ,是正确去掉超链接标识了,但上例的表达式壮健性太差了,稍有变化,就会出错。
稍变一下:
$str="111<a href=''></a>88"; // 如果href 前面多几个空格
echo preg_replace("/<a href=''>|<\/a>/i","",$str); //输出111<a href=''>88, 这样就出错了。
因此我们再将其改进一下:
$str="111<a href=''></a>88";
echo preg_replace("/<a href=''>|<\/a>/i","",$str);
作业题:
下面是一条壮健性比较好的替换超链接代码的表达式, 好好分析一下
echo preg_replace("/<a\s+href=[^>]*>|<\/[^a]*a[^>]*>/i","",$str);