天天看點

正規表達式(入門)定錨點,去噪點,取資料

關于正則字元,很多文章都會講到,足足有一篇文章才能描述清楚,我這裡就不多說,對于我,平時,常用的有:

<code>.</code> 比對不包括換行的任意字元,在php的s修飾符下面可以比對換行,如<code>$pattern='#&lt;div&gt;(.*?)&lt;/div&gt;#s';</code>就可以比對div内容有換行的資料。

<code>\s</code> 空格、tab

<code>*</code> 比對零個或多個

<code>+</code> 比對一個或多個,即至少一個

<code>\</code> 轉義

一個特殊字元前加<code>\</code>就表示轉義,說明把它當普通字元用

<code>[]</code> 單字元取一個,比如[abc]會比對<code>a或b或c</code>

但是,如果<code>[]</code>裡面加上<code>^</code>則會變成排除這個字元,如<code>[^abc]</code>就表示<code>不是a、不是b、也不是c</code> 

另外,在<code>[]</code>裡面可以使用<code>-</code>表示一個範圍,如<code>[0-9]</code>表示從0到9,類似的還有<code>[a-zA-Z]</code>,如果要包含<code>-</code>字元,可以給它加上轉義<code>[\-]</code>

<code>^</code> 一行字元串開始(虛拟字元,不實際存在)

這裡的^跟<code>[]</code>裡面用的<code>^</code>是同一個字元,但是卻不是一個意思,這裡它表示一行字元串的開始,比如<code>^www</code>表示以<code>www</code>開頭的字元串,注意區分,不在<code>[]</code>裡面的是開始符,在裡面的排除

<code>$</code> 一行字元串結束(虛拟字元,不實際存在)

<code>{1,3}</code> 循環次數

<code>[0-9]{1,3}</code>表示在0-9的範圍裡面循環1個、2個或者3個,可能結果有5、20、415等

<code>?</code> 有兩個用法

(1) 比對一個或零個,比如<code>https?</code>比對的<code>https</code>(一個s)或者http(零個s)

(2)非貪婪模式

所謂非貪婪模式,就是比對盡可能少的内容,比如,對于源字元串

<code>&lt;div&gt;</code>

<code>a</code>

<code>&lt;/div&gt;</code>

<code>b</code>

使用<code>&lt;div&gt;(.*?)&lt;/div&gt;</code>會得到2個結果:

因為,當遇到第一個<code>&lt;/div&gt;</code>,非貪婪模式就不會再往後找了。 

而使用<code>&lt;div&gt;(.*)&lt;/div&gt;</code>(貪婪模式)則會得到整個字元串

,因為它會比對所有字元直到後面再找不到<code>&lt;/div&gt;</code>。 

11. <code>|</code> 多個資料選一(常用于多字元) 

前面提到<code>[]</code>裡面的字元有選一個字元功能,但是假如不是一個字元,比如:http|ftp|svn 就需要用<code>|</code>分開,<code>|</code>的作用域是一直往後直到遇到括号,比如,對于源字元串

<code>http abc</code>

<code>ftp abc</code>

<code>svn abc</code>

<code>http|ftp|svn abc</code>比對的結果是:

<code>http</code>

<code>ftp</code>

想要比對 <code>http abc</code>和<code>ftp abc</code>和<code>svn abc</code>就要使用括号把前邊的協定括起來,如<code>(http|ftp|svn) abc</code> 可以得到預期的結果。 

12. <code>()</code> 資料分界和取資料

上面例子<code>(http|ftp|svn) abc</code>就是資料分界的例子,然後,比對結果會得到一個[1]的子集資料,這裡就是子模式的概念,利用子模式,可以得到想要取出來的資料。子模式1、2、3的計算方法為左括号的計數,從左到右,從1開始,比如: 

<code>(http|ftp|svn)://([^/]+)</code>,[1]得到的是<code>(http|ftp|svn)</code>裡面的資料,[2]得到<code>([^/]+)</code>裡面的資料,對于嵌套括号也是點左括号即可。 

13. <code>(?:)</code> 非捕獲組 

上面說到<code>()</code>作為子模式可以得到它裡面的資料,但是,有些時候,<code>()</code>隻是作為資料分界功能,并不需要取出來,這時候就要用到非捕獲組的概念了。比如:<code>(http|ftp|svn)://([^/]+)</code>隻想得到域名,也就是[2],那麼<code>(http|ftp|svn)</code>就隻是資料分界的功能,這裡不需要捕獲,是以使用非捕獲組功能,<code>(?:http|ftp|svn)</code>屏蔽這部分的資料擷取,此時,<code>(?:</code>這個左括号要排除出[1]、[2]計數,也就是<code>(?:http|ftp|svn)://([^/]+)</code>中的<code>([^/]+)</code>變成[1]了。

每一個正則都是有針對性的,隻有這樣正則才有意義。是以,寫正則之前,先觀察你要解析的資料,找準唯一的錨點,比如,你要解析一個頁面的title标簽,得到title内容,那麼這個title就是錨點。有時候,所要取的資料确實無法定位一個唯一的錨點,那麼,你可以分解資料,先通過一個唯一錨點鎖定你的資料塊,取出來之後,再對這個資料塊取資料即可。比如,有這麼一段源字元串:

<code>&lt;div id="module_1"&gt;</code>

<code>&lt;div class="content"&gt;</code>

<code>content 1</code>

<code>&lt;div id="module_2"&gt;</code>

<code>content 2</code>

你直接通過class="content"來比對資料的話很明顯會得到兩個,那麼,你可以擴充它的資料域,先以id="module_1"作為錨點,擷取整個

然後在對這個資料塊的資料處理,得到class="contents"的内容即可。 

是以,這裡用到2個正則:

(1)<code>&lt;div id="module_1"&gt;(.*?)&lt;/div&gt;\s*&lt;div id="module_2"&gt;</code> 

(2)<code>&lt;div class="content"&gt;(.*?)&lt;/div&gt;</code>

所謂去噪點,就是把無關的東西都當浮雲,用通配符過掉它,隻關心我們想要的資料,比如: 

<code>&lt;meta content="text/html; charset=utf-8" http-equiv="content-type"&gt;</code> 

要從這裡得到字元集utf-8,我們需要怎麼做? 

首先,定位錨點,有<code>&lt;meta</code> 、<code>charset=</code>和utf-8後面的<code>"</code>,其他都是浮雲~ 

是以得到正則: 

<code>&lt;meta[^&gt;]*charset=([^"]+)"</code> 

即可,用子模式取資料[1]就能得到utf-8

關于取資料,上面一大篇下來大家應該有概念了,就是利用子模式來擷取,這裡不再贅述。

本文轉自左正部落格園部落格,原文連結:http://www.cnblogs.com/soundcode/p/3807341.html,如需轉載請自行聯系原作者