php正則逆向引用與子模式分析

狗子2018發表於2015-05-08

先看一個例子:

<?php
$string = `April 15, 2003`;
$pattern = `/(w+) (d+), (d+)/i`;
$replacement = `${1}1,$3`;
echo preg_replace($pattern, $replacement, $string);
?>

View Code

例子的結果是:April1,2003

 

函式preg_replace ( mixed pattern, mixed replacement, mixed subject [, int limit])

在 subject 中搜尋 pattern 模式的匹配項並替換為 replacement。如果指定了 limit,則僅替換 limit 個匹配,如果省略 limit 或者其值為 -1,則所有的匹配項都會被替換。
replacement可以包含\n形式或$n形式的逆向引用,n可以為0到99,\n表示匹配pattern第n個子模式的文字,\0表示匹配整個pattern的文字。

所謂“子模式”就是:$pattern引數中被圓括號括起來的正規表示式(pattern即為模式)。

 

對上面例子中的 $replacement = `${1}1,$3`;  

因為當在替換模式下工作並且後向引用後面緊跟著需要是另外一個數字, 不能使用\1這樣的語法來描述後向引用。\11將會使preg_replace() 不能理解你希望的是一個\1後向引用緊跟一個原文1,還是 一個\11後向引用後面不跟任何東西。 這種情況下解決方案是使用${1}1。 這建立了一個獨立的$1後向引用, 一個獨立的原文1

 

再看一個例子:

<?php 
$string = "Is is the cost of of gasoline going up up"; 
$pattern = "/([a-z]+) \1/i"; //這裡的\1不能使用$1或$1 
$str = preg_replace($pattern, "\1", $string); //這裡的\1可以使用$1或$1,引用第一個子匹配 
echo $str; 
?> 

View Code

結果為:Is the cost of gasoline going up    去掉了重複的內容。

例中的子表示式就是圓括號內的項。匹配單詞的開始或結束。+匹配重複一次或更多次。 
該子表示式匹配的是一個或多個字母字元的單詞,即由`[a-z]+`匹配的。 
該正規表示式的第二部分是對前面所捕獲的子匹配的引用,也就是由附加表示式所匹配的第二次出現的單詞,用`\1`來引用第一個子匹配,第一個是轉義符。 
i是正規表示式中的修正符。i:忽略大小寫。 

 

擴充套件:一個常見的面試題

在file.txt中按行存放著這樣的一些數字

0013223544456
013423545456
1372-35–45456
132245-44556
13723-584456
1392-3544-456
132-255444-56
0132-275444-56

希望對其進行處理:除去首位的0,除去字串中包含的-符號,並且將手機號碼處理成132****456格式,處理後儲存在newfile.txt檔案中。

我的方法是:

<?php
$fp = fopen("file.txt", "r");
$newf = fopen("newfile.txt", "w"); 
while(! feof($fp)) 
{ 
$fgets = fgets($fp);
$fgets = preg_replace(`/^0*|D/`, ``, $fgets);
$pattern = "/(1d{1,2})dd(d{0,3})/";
$replacement = "$1****$3";
$fgets = preg_replace($pattern, $replacement, $fgets);
$text = $fgets."
";
fwrite($newf, $text);

} 
fclose($fp); 
fclose($newf);
?>

View Code

 

newfile.txt中最總結果是:

132****456
134****456
137****456
132****556
137****456
139****456
132****456
132****456

 




相關文章