正则表达式之难点
2017-10-20 本文已影响65人
荆棘路上的猴子
- 断言
-
?<=
这个是对需要匹配的目标左边的(前面)的进行断言,断定它前面会出现的 但是不会被匹配到。如:
$subject = 'I am Lancer, Please say hello Lancer';
//目标: 我要把hello 后面的Lancer 改为 '!' .
$pattern = '/(?<=hello )Lancer/';
$result = preg_replace($pattern, '', $subject);
echo $result; //I am Lancer, Please say hello !
这样就成功咯~
-
?=
,与上面的位置刚好相反,这个是对需要匹配的目标右边的(后面)的进行断言,断定它后面会出现的 但是不会被匹配到。如:
$subject = 'I love you! I love her too!';
//目标:不能爱这么多, 把第二个 'love' 改为 'hate'
$pattern = '/love(?= her)/';
$result = preg_replace($pattern, 'hate', $subject);
echo $result; //'I love you! I hate her too!'
-
?<!
这个是需要对匹配左边的(前面的)进行断言,不过它是非,找到不是这个的。还是拿第一个例子来说:
$subject = 'I am Lancer, Please say hello Lancer';
//目标: 我还是要把hello 后面的Lancer 改为 '!' 该怎么做
$pattern = '/(?<!am )Lancer/'; //找到‘Lancer’前面不是'am '的'Lancer'
$result = preg_replace($pattern, '', $subject);
echo $result; //I am Lancer, Please say hello !
-
?!
还是一样的秘方,还是一样的味道~
$subject = 'I love you! I love her too!';
//目标:不能爱这么多, 把第二个 'love' 改为 'hate'
$pattern = '/love(?! you)/';
$result = preg_replace($pattern, 'hate', $subject);
echo $result; //'I love you! I hate her too!'
总结:这个断言,作用主要在,对于很多同样的目标,可是我只要其中的一个,或者多个的时候,那么就可以根据它的前面和后面,进行断言,来区分他们找到自己想要匹配的目标。
-
捕获
先来说一下, 什么叫捕获。就是匹配之后,会根据你正则表达式中的()来进行分组。一一捕获。打个比方:
//为了显示方便,写了个show函数
function show($str)
{
if (empty($str)) {
echo null;
} elseif (is_array($str) || is_object($str)) {
echo '<pre>';
print_r($str);
echo '</pre>';
} else {
echo $str;
}
}
//--------------------------------------------------------------------
$subject = '12323abcdea1233';
$pattern = '/(a)(b)(c)(d)(e)/';
preg_match_all($pattern, $subject, $matches);
show($matches);
//那么你会觉得 $matches 会是什么答案?
//你肯定知道是:
Array
(
[0] => Array
(
[0] => abcde
)
[1] => Array
(
[0] => a
)
[2] => Array
(
[0] => b
)
[3] => Array
(
[0] => c
)
[4] => Array
(
[0] => d
)
[5] => Array
(
[0] => e
)
)
//这个答案,大家应该都知道吧。索引为0的是整个match的内容,接着的
//就是捕获的每一个()分组的内容。我们还可以这样来写:
$subject = '123abcabc123';
$pattern = '/(a)(b)(c)(\1)(\2)(\3)/';
preg_match_all($pattern, $subject, $matches);
show($matches);//??
先看答案:
Array
(
[0] => Array
(
[0] => abcabc
)
[1] => Array
(
[0] => a
)
[2] => Array
(
[0] => b
)
[3] => Array
(
[0] => c
)
[4] => Array
(
[0] => a
)
[5] => Array
(
[0] => b
)
[6] => Array
(
[0] => c
)
)
//你可能会有疑问, 咦,,, 怎么(\1)和(a), (\2)和(b),(\3)和(c) 在正则里是一样的呢?
//其实 (a)就是指的第一组, 然后后面就可以用(\1)来表示。(b),(c)也一样。
有人可能就会问了, 那你写这个的作用又是什么呢 ? 获取这些括号里的干啥。。 我只要第一个索引的匹配就够了呀。
但是, 你考虑到了替换这个因素没? 如果我替换的时候需要()的东西呢? 这个时候,我们就可以用到捕获到的()的东西来穿插。
不知道有人好奇过没,为什么用那些TP框架,Laravel框架, 或者smarty
在模版里写的{{$msg}}为什么也能输出呢?
其实就是用了正则替换~ 看代码:
$msg = "正则捕获";
$subject = '<p>{{$msg}}</p>';
$pattern = '/\{\{(.*/)\}\}/'; //因为正则里也有'{' 和'}'所以需要用‘\’转义
$result = preg_replace($pattern, '<?php echo $1; ?>', $subject);
show($result); // <p><?php echo $msg;?></p>
//成功修改~
上面说的是捕获, 但是我可能不想捕获怎么办? 那么就可以用(?:)
在前面加上?:
即可。注意, 这个不会影响匹配 只会影响捕获。
如:
$subject = 'abc';
$pattern = '/(a)(?:b)(c)/';
preg_match_all($pattern, $subject, $matches);
show($matches);
//结果:
Array
(
[0] => Array
(
[0] => abc
)
[1] => Array
(
[0] => a
)
[2] => Array
(
[0] => c
)
)
//看 匹配的结果让然是'abc' 不过没有捕获到 'b'
以上就是基本的难点了, 纯手打和个人想法写完~ 谢谢观看,欢迎吐槽!