我眼里的正則表達式(入門)


正則對於新人來說是一個頭疼的名字,讓人聞而生畏。但是,在我看來,正則,並沒有那么神秘。

接觸正則應該有三年不止了吧,我也不知道自己怎么就走過了畏懼正則的時期,而且在一個小圈子里面還成了正則強人。

今天就基於我對正則的理解,簡單描述一下我眼里的正則,希望能夠解除正則新人對於正則的畏懼感。

先概括一下,正則三段論:

定錨點,去噪點,取數據

1、入門:正則字符

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

  1. . 匹配不包括換行的任意字符,在php的s修飾符下面可以匹配換行,如$pattern='#<div>(.*?)</div>#s';就可以匹配div內容有換行的數據。

  2. \s 空格、tab

  3. * 匹配零個或更多個,即0~n

  4. + 匹配一個或更多個,即至少一個,1~n

  5. \ 轉義
    一個特殊字符前加\就表示轉義,說明把它當普通字符用

  6. [] 單字符取一個,比如[abc]會匹配a或b或c

    但是,如果[]里面加上^則會變成排除這個字符,如[^abc]就表示不是a、不是b、也不是c
    另外,在[]里面可以使用-表示一個范圍,如[0-9]表示從0到9,類似的還有[a-zA-Z],如果要包含-字符,可以給它加上轉義[\-]
    關於[]常見的錯誤用法是:[ab|bc]用來表示abbc,實際上,它得到的結果是[abc|],即a或b或c或|這4個字符(單字符)的任意一個。這里可以改成(ab|bc)
    總結:[]里面的特殊符有五個:[]-\^,其他字符都是普通字符,包括*.?等。
    說明:

    • ^[^ 的首位時候才有特殊意義
    • [0-9 -在不是首尾的時候有特殊意義
    • \[ \] 因為占用[] 本身字符,所以有特殊意義
    • \本身是轉義符,有特殊意義
  7. ^ 字符串開始
    這里的^跟[]里面用的^是同一個字符,但是卻不是一個意思,這里它表示整個字符串的開始,比如^www表示以www開頭的字符串,注意區分,不在[]里面的是開始符,在里面的排除

  8. $ 字符串結束

  9. {1,3} 循環次數
    [0-9]{1,3}表示在0-9的范圍里面循環1個、2個或者3個,可能結果有5、20、415等。
    如果循環指定次數,如3次,則{3,3}可以簡寫成{3}
    如果剛好需要匹配字符{1},則正則需要給{進行轉義,得到\{1}的正則。
    如果{}中間不是數字,則{}本身不需要轉義。

  10. ? 有兩個用法
    (1) 匹配一個或零個,比如https?匹配的https(一個s)或者http(零個s)
    (2)非貪婪模式
    所謂非貪婪模式,就是匹配盡可能少的內容,比如,對於源字符串

<div>a</div><div>b</div>

使用<div>(.*?)</div>會得到2個結果(注意:如果源字符串有換行,使用[\s\S]替換 . ):

<div>a</div>

<div>b</div>

因為,當遇到第一個</div>,非貪婪模式就不會再往后找了。
而使用<div>(.*)</div>(貪婪模式)則會得到整個字符串

<div>a</div><div>b</div>

,因為它會匹配所有字符直到后面再找不到</div>

  1. | 多個數據選一(常用於多字符)
    前面提到[]里面的字符有選一個字符功能,但是假如不是一個字符,比如:http|ftp|svn 就需要用|分開,|的作用域是一直往后直到遇到括號,比如,對於源字符串
http abc
ftp abc
svn abc

http|ftp|svn abc匹配的結果是:

http

ftp

svn abc

想要匹配 http abcftp abcsvn abc就要使用括號把前邊的協議括起來,如(http|ftp|svn) abc 可以得到預期的結果。

  1. () 數據分界和取數據
    上面例子(http|ftp|svn) abc就是數據分界的例子,然后,匹配結果會得到一個1的子集數據,這里就是子模式的概念,利用子模式,可以得到想要取出來的數據。子模式1、2、3的計算方法為左括號的計數,從左到右,從1開始,比如:
    (http|ftp|svn)://([^/]+)1得到的是(http|ftp|svn)里面的數據,[2]得到([^/]+)里面的數據,對於嵌套括號也是點左括號即可。

  2. (?:) 非捕獲組
    上面說到()作為子模式可以得到它里面的數據,但是,有些時候,()只是作為數據分界功能,並不需要取出來,這時候就要用到非捕獲組的概念了。比如:(http|ftp|svn)://([^/]+)只想得到域名,也就是[2],那么(http|ftp|svn)就只是數據分界的功能,這里不需要捕獲,因此使用非捕獲組功能,(?:http|ftp|svn)屏蔽這部分的數據獲取,此時,(?:這個左括號排除1計數,也就是(?:http|ftp|svn)://([^/]+)中的([^/]+)變成1了。


關於常用字符的使用差不多到這里,還有更多的請參考正則表達式30分鍾入門教程,這是我看過比較全面的正則入門資料。

2、 操作:定錨點

每一個正則都是有針對性的,只有這樣正則才有意義。因此,寫正則之前,先觀察你要解析的數據,找准唯一的錨點,比如,你要解析一個頁面的title標簽,得到title內容,那么這個title就是錨點。有時候,所要取的數據確實無法定位一個唯一的錨點,那么,你可以分解數據,先通過一個唯一錨點鎖定你的數據塊,取出來之后,再對這個數據塊取數據即可。比如,有這么一段源字符串:

<div id="module_1">
    <div class="content">
              content 1
    </div>
</div>
<div id="module_2">
    <div class="content">
              content 2
    </div>
</div>

你直接通過class="content"來匹配數據的話很明顯會得到兩個,那么,你可以擴展它的數據域,先以id="module_1"作為錨點,獲取整個

<div id="module_1">
    <div class="content">
              content 1
    </div>
</div>

然后在對這個數據塊的數據處理,得到class="contents"的內容即可。
因此,這里用到2個正則:

(1)<div id="module_1">(.*?)</div>\s*<div id="module_2">
(2)<div class="content">(.*?)</div>

總結:錨點,就是能唯一定位你數據的標識

3、 操作:去噪點

所謂去噪點,就是把無關的東西都當浮雲,用通配符過掉它,只關心我們想要的數據,比如:
<meta content="text/html; charset=utf-8" http-equiv="content-type">
要從這里得到字符集utf-8,我們需要怎么做?
首先,定位錨點,有<metacharset=和utf-8后面的",其他都是浮雲~
因此得到正則:
<meta[^>]*charset=([^"]+)"
即可,用子模式取數據[1]就能得到utf-8

總結:關心的留下,不關心的都是浮雲

4、 操作:取數據

關於取數據,上面一大篇下來大家應該有概念了,就是利用子模式來獲取,這里不再贅述。

總結:子模式計數,數左括號從1開始,排除非捕獲組的左括號

最后,希望大家有一個愉悅的正則之旅,你一定會愛上她的,跟我一樣。: )

原文發表自Zjmainstay學習筆記 我眼里的正則表達式


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM