本文轉自 coffeephp
斷言
?<=
這個是對需要匹配的目標左邊的(前面)的進行斷言,斷定它前面會出現的 但是不會被匹配到。如:
$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'
本作品採用《CC 協議》,轉載必須註明作者和本文連結