正則表達式(JavaScript)

正則表達式(JavaScript)javascript

正則表達式(JavaScript)

1. 瞭解正則表達式

1.1. 什麼是正則表達式

正則表達式(regular expression)描述了一種字符串匹配的模式,能夠用來檢查一個串是否含有某種子串、將匹配的子串作替換或者從某個串中取出符合某個條件的子串等。java

  • 列出目錄時,dir .txt 或 ls .txt 中的 .txt 就不是一個正則表達式,由於這裏 與正則式的 * 的含義是不一樣的。
  • 構造正則表達式的方法和建立數學表達式的方法同樣。也就是用多種元字符與運算符能夠將小的表達式結合在一塊兒來建立更大的表達式。正則表達式的組件能夠是單個的字符、字符集合、字符範圍、字符間的選擇或者全部這些組件的任意組合。

正則表達式是由普通字符(例如字符 a 到 z)以及特殊字符(稱爲」元字符」)組成的文字模式。模式描述在搜索文本時要匹配的一個或多個字符串。正則表達式做爲一個模板,將某個字符模式與所搜索的字符串進行匹配。正則表達式

1.2. 經常使用的正則表達式匹配工具

2. 正則表達式語法

2.1. 建立正則表達式

咱們有兩種方式構造正則表達式:express

  1. 使用RegExp對象構造函數構造一個正則表達式對象。
    var reg = new RegExp("abc");
  2. 使用斜槓(/)字符將模式包圍起來,生成一個字面值。
    var reg = /abc/;

2.2. 元字符

正則表達式由兩種基本字符類型組成:數組

  • 原義文本字符
  • 元字符

元字符是指在正則表達式中有特殊含義的非字母字符,下表包含了元字符的完整列表以及它們在正則表達式上下文中的行爲:函數

字符 描述
\ 將下一個字符標記爲一個特殊字符、或一個原義字符、或一個 向後引用、或一個八進制轉義符。例如,’n’ 匹配字符 「n」。’\n’ 匹配一個換行符。序列 ‘\’ 匹配 「\」 而 「(」 則匹配 「(「。
^ 匹配輸入字符串的開始位置。若是設置了 RegExp 對象的 Multiline 屬性,^ 也匹配 ‘\n’ 或 ‘\r’ 以後的位置。
$ 匹配輸入字符串的結束位置。若是設置了RegExp 對象的 Multiline 屬性, 它也匹配 ‘\n’ 或 ‘\r’ 以前的位置。
* 匹配前面的子表達式零次或屢次。例如,zo* 能匹配 「z」 以及 「zoo」。* 等價於{0,}。
+ 匹配前面的子表達式一次或屢次。例如,’zo+’ 能匹配 「zo」 以及 「zoo」,但不能匹配 「z」。+ 等價於 {1,}。
? 匹配前面的子表達式零次或一次。例如,」do(es)?」 能夠匹配 「do」 或 「does」 中的」do」 。? 等價於 {0,1}。
{n} n 是一個非負整數。匹配肯定的 n 次。例如,’o{2}’ 不能匹配 「Bob」 中的 ‘o’,可是能匹配 「food」 中的兩個 o。
{n,} n 是一個非負整數。至少匹配n 次。例如,’o{2,}’ 不能匹配 「Bob」 中的 ‘o’,但能匹配 「foooood」 中的全部 o。’o{1,}’ 等價於 ‘o+’。’o{0,}’ 則等價於 ‘o*’。
{n,m} m 和 n 均爲非負整數,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,」o{1,3}」 將匹配 「fooooood」 中的前三個 o。’o{0,1}’ 等價於 ‘o?’。請注意在逗號和兩個數之間不能有空格。
? 當該字符緊跟在任何一個其餘限制符 (*, +, ?, {n}, {n,}, {n,m}) 後面時,匹配模式是非貪婪的。非貪婪模式儘量少的匹配所搜索的字符串,而默認的貪婪模式則儘量多的匹配所搜索的字符串。例如,對於字符串 「oooo」,’o+?’ 將匹配單個 「o」,而 ‘o+’ 將匹配全部 ‘o’。
. 匹配除 「\n」 以外的任何單個字符。要匹配包括 ‘\n’ 在內的任何字符,請使用像」(.
(pattern) 匹配 pattern 並獲取這一匹配。所獲取的匹配能夠從產生的 Matches 集合獲得,在VBScript 中使用 SubMatches 集合,在JScript 中則使用 9 屬性。要匹配圓括號字符,請使用 ‘(’ 或 ‘)’。
(?:pattern) 匹配 pattern 但不獲取匹配結果,也就是說這是一個非獲取匹配,不進行存儲供之後使用。這在使用 「或」 字符 (
(?=pattern) 正向預查,在任何匹配 pattern 的字符串開始處匹配查找字符串。這是一個非獲取匹配,也就是說,該匹配不須要獲取供之後使用。例如,’Windows (?=95
(?!pattern) 負向預查,在任何不匹配 pattern 的字符串開始處匹配查找字符串。這是一個非獲取匹配,也就是說,該匹配不須要獲取供之後使用。例如’Windows (?!95
x y
[xyz] 字符集合。匹配所包含的任意一個字符。例如, ‘[abc]’ 能夠匹配 「plain」 中的 ‘a’。
[^xyz] 負值字符集合。匹配未包含的任意字符。例如, ‘[^abc]’ 能夠匹配 「plain」 中的’p’、’l’、’i’、’n’。
[a-z] 字符範圍。匹配指定範圍內的任意字符。例如,’[a-z]’ 能夠匹配 ‘a’ 到 ‘z’ 範圍內的任意小寫字母字符。
[^a-z] 負值字符範圍。匹配任何不在指定範圍內的任意字符。例如,’[^a-z]’ 能夠匹配任何不在 ‘a’ 到 ‘z’ 範圍內的任意字符。
\b 匹配一個單詞邊界,也就是指單詞和空格間的位置。例如, ‘er\b’ 能夠匹配」never」 中的 ‘er’,但不能匹配 「verb」 中的 ‘er’。
\B 匹配非單詞邊界。’er\B’ 能匹配 「verb」 中的 ‘er’,但不能匹配 「never」 中的 ‘er’。
\cx 匹配由 x 指明的控制字符。例如, \cM 匹配一個 Control-M 或回車符。x 的值必須爲 A-Z 或 a-z 之一。不然,將 c 視爲一個原義的 ‘c’ 字符。
\d 匹配一個數字字符。等價於 [0-9]。
\D 匹配一個非數字字符。等價於 [^0-9]。
\f 匹配一個換頁符。等價於 \x0c 和 \cL。
\n 匹配一個換行符。等價於 \x0a 和 \cJ。
\r 匹配一個回車符。等價於 \x0d 和 \cM。
\s 匹配任何空白字符,包括空格、製表符、換頁符等等。等價於 [ \ f\n\r\t\v]。
\S 匹配任何非空白字符。等價於 [^ \f\n\r\t\v]。
\t 匹配一個製表符。等價於 \x09 和 \cI。
\v 匹配一個垂直製表符。等價於 \x0b 和 \cK。
\w 匹配包括下劃線的任何單詞字符。等價於’[A-Za-z0-9_]’。
\W 匹配任何非單詞字符。等價於 ‘[^A-Za-z0-9_]’。
\xn 匹配 n,其中 n 爲十六進制轉義值。十六進制轉義值必須爲肯定的兩個數字長例如,’\x41’ 匹配 「A」。’\x041’ 則等價於 ‘\x04’ & 「1」。正則表達式中可使用 ASCII 編碼。
\num 匹配 num,其中 num 是一個正整數。對所獲取的匹配的引用。例如,’(.)\1’ 匹配兩個連續的相同字符。
\n 標識一個八進制轉義值或一個向後引用。若是 \n 以前至少 n 個獲取的子表達式,則 n 爲向後引用。不然,若是 n 爲八進制數字 (0-7),則 n 爲一個八進制轉義值。
\nm 標識一個八進制轉義值或一個向後引用。若是 \nm 以前至少有 nm 個得到子表達式,則 nm 爲向後引用。若是 \nm 以前至少有 n 個獲取,則 n 爲一個後跟文字 m 的向後引用。若是前面的條件都不知足,若 n 和 m 均爲八進制數字 (0-7),則 \nm 將匹配八進制轉義值 nm。
\nml 若是 n 爲八進制數字 (0-3),且 m 和 l 均爲八進制數字 (0-7),則匹配八進制轉義值 nml。
\un 匹配 n,其中 n 是一個用四個十六進制數字表示的 Unicode 字符。例如,
\u00A9 匹配版權符號 (?)。

2.3. 字符類和範圍類以及邊界

咱們要取某一類字符的時候可使用中括號加字符的形式,例如:[abc]匹配中括號中內元素的字符,好比能夠匹配」plain」中的’a’。
正則表達式還提供了範圍類,咱們可使用[a-z]匹配a到z的字符,若是想要匹配全部的大小寫字母,則能夠用[a-zA-Z]。工具

在中括號中使用^表示取反,例如[^a-z]匹配不在a-z範圍內的字符。可是用在正則表達式中表示匹配輸入字符串的起始位置。編碼

正則表達式給咱們提供了一些預約義類來方便咱們的使用,例如.、\d、\w、\s等,具體用法見上表。
正則表達式還提供了幾個經常使用的邊界匹配符,以下:spa

字符 含義
^ 匹配輸入字符串的開始位置。若是設置了 RegExp 對象的 Multiline 屬性,^ 也匹配 ‘\n’ 或 ‘\r’ 以後的位置。
$ 匹配輸入字符串的結束位置。若是設置了RegExp 對象的 Multiline 屬性, 它也匹配 ‘\n’ 或 ‘\r’ 以前的位置。
\b 匹配一個單詞邊界,也就是指單詞和空格間的位置。例如, ‘er\b’ 能夠匹配」never」 中的 ‘er’,但不能匹配 「verb」 中的 ‘er’。
\B 匹配非單詞邊界。’er\B’ 能匹配 「verb」 中的 ‘er’,但不能匹配 「never」 中的 ‘er’。

2.4. 量詞

先解釋三個概念prototype

  • 貪婪(貪心) 如」*」字符 貪婪量詞會首先匹配整個字符串,嘗試匹配時,它會選定儘量多的內容,若是 失敗則回退一個字符,而後再次嘗試回退的過程就叫作回溯,它會每次回退一個字符,直到找到匹配的內容或者沒有字符能夠回退。相比其餘兩種貪婪量詞對資源的消耗是最大的。
  • 懶惰(勉強) 如 「?」 懶惰量詞使用另外一種方式匹配,它從目標的起始位置開始嘗試匹配,每次檢查一個字符,並尋找它要匹配的內容,如此循環直到字符結尾處。
  • 佔有 如」+」 佔有量詞會覆蓋事個目標字符串,而後嘗試尋找匹配內容 ,但它只嘗試一次,不會回溯,就比如先抓一把石頭,而後從石頭中挑出黃金。

經常使用的量詞有:

字符 含義
* 匹配前面的子表達式零次或屢次。(貪婪)
+ 匹配前面的子表達式一次或屢次。(懶惰)
? 匹配前面的子表達式零次或一次。(佔有)
{n} n 是一個非負整數。匹配肯定的 n 次。
{n,} n 是一個非負整數。至少匹配n 次。
{n,m} m 和 n 均爲非負整數,其中n <= m。最少匹配 n 次且最多匹配 m 次。

正則表達式默認爲貪婪模式,儘量多的去匹配,若是想要讓正則表達式儘量少的匹配,則須要用到」?」
當」?」緊跟在任何一個其餘限制符 (*, +, ?, {n}, {n,}, {n,m}) 後面時,匹配模式是非貪婪的。非貪婪模式儘量少的匹配所搜索的字符串,而默認的貪婪模式則儘量多的匹配所搜索的字符串。例如,對於字符串 「oooo」,’o+?’ 將匹配單個 「o」,而 ‘o+’ 將匹配全部 ‘o’。

字符 含義
*? 重複任意次,但儘量少重複
+? 重複1次或更屢次,但儘量少重複
?? 重複0次或1次,但儘量少重複
{n,m}? 重複n到m次,但儘量少重複
{n,}? 重複n次以上,但儘量少重複

3. 正則表達式進階

3.1. 分組和或

正則表達式中正常狀況下量詞只對前一個字符或字符類起做用,若是想讓他對固定的字符串起做用,就須要分組。分組其實就是一個括號裏的內容,可使量詞做用於分組,例如/(tristan){1,3}/括號中就是一個分組。

「或」的概念就是匹配一個字符串或者另外一個字符串,用」|」表示,例如/Tristan | Henry/,沒有分組的狀況下或做用於字符串,有分組的狀況下或做用於分組,例如/Trist(an | He)nry/。

反向引用,當咱們替換或者其餘操做須要前面引用替換的字符串時,可使用」$」符號依次獲得匹配的分組的字符串。例如,將」2017-02-08」替換爲」02/08/2017」,須要替換的字符串不多是一成不變的,因此須要使用反向引用,方法爲:
'2017-02-08'.replace(/(\d{4})-(\d{2})-(\d{2})/g, '$2/$3$1');

Alt text

關於分組常有的用法以下:

字符 含義
(exp) 匹配exp,並捕獲文本到自動命名的組裏
(?<\name>exp) 匹配exp,並捕獲文本到名稱爲name的組裏
(?:exp) 匹配exp,不捕獲匹配的文本,也不給此分組分配組號 Alt text

3.2 前瞻

正則表達式從文本頭部向尾部開始解析,文本尾部方向成爲前。

前瞻就是在正則表達式匹配到規則的時候,向前檢查是否符合斷言,後顧/後瞻方向相反。JavaScript不支持後顧。
符合和不符合特定斷言成爲確定/正向匹配和否認/負向匹配。

名稱 正則 含義
正向前瞻 exp(?=assert) 前面正則表達式匹配而且後面符合斷言Alt text
負向前瞻 exp(?!assert) 前面正則表達式匹配而且後面不符合斷言Alt text
正向後顧 exp(?<=assert) JavaScript不支持
負向後顧 exp(? JavaScript不支持

4. JavaScript中的正則表達式

4.1. 對象屬性

  • global: 是否全局搜索,默認爲false(只讀);
  • ignoreCase: 是否大小寫敏感,默認爲false(只讀);
  • multiline: 是否多行搜索,默認爲false(只讀);
  • lastIndex: 是當前表達式匹配內容的最後一個字符的下一個位置,當正則表達式啓用了全局(g)而且使用exec匹配模式時可使用;
  • source: 正則表達式的文本字符串;

4.2. test和exec方法

  1. RegExp.prototype.test(str):
    • 用於檢測字符串參數中是否存在匹配正則表達式模式的字符串
    • 若是存在則返回true,不然返回false

注意:正則表達式爲全局搜索時,會出現屢次執行結果不一致問題,緣由爲全局搜索模式下,每次執行方法會在lastIndex屬性的位置開始搜索,而lastIndex屬性隨着每次搜索而改變,這樣在匹配完最後一個匹配結果後剩下的字符串就沒有了匹配結果,test方法就會返回false。因此test方法儘可能不要用全局搜索(非全局下lastIndex不生效)。

  1. RegExp.prototype.exec(str):
    • 使用正則表達式模式對字符串執行搜索,並更新全局RegExp對象的屬性以反映匹配結果。
    • 若是沒有匹配的文本則返回null,不然返回一個結果數組:
      - index 聲明匹配文本的第一個字符的位置
      - input 存放被檢索的字符串string

調用非全局的RegExp對象的exec()時,返回數組:

  • 第一個元素是與正則表達式相匹配的文本
    • 第二個元素是與RegExpObject的第一個子表達式(一個分組)匹配的文本(若是有的話)
    • 第三個元素是與RegExpObject的第二個子表達式(一個分組)相匹配的文本(若是有的話),以此類推

調用全局的RegExp對象的exec()時,能夠循環獲得全部的匹配字符串。

4.3. 字符串對象方法

  1. String.protatype.search(reg):

    • 檢索字符串中是否有指定子字符串,或是否有與正則表達式相匹配的子字符串
    • 方法返回第一個匹配結果的index,沒有匹配返回-1
    • 方法不執行全局匹配,它忽略標誌g,而且老是從字符串的開始進行檢索
  2. String.protatype.match(reg):

    • match()方法將檢索字符串,以找到一個或多個與reg匹配的字符串
    • reg是否具備標誌g對結果影響很大

若是reg沒有標誌g,那麼march()方法就只能在字符串中執行一次匹配,若是沒有找到匹配文本返回null,不然返回一個數組,其中存放了與他找到的匹配文本有關的信息:

  • 第一個元素存放的是匹配文本,其他元素存放的是與正則表達式的子表達式匹配的文本
  • 數組還含有兩個對象屬性:indexinput

若是reg具備標誌g,則march()方法將執行全局檢索,找到字符串中的全部匹配子字符串,若是沒有找到任何匹配的子串,返回null;若是找到了一個或多個匹配子串,則返回一個數組,其中存放字符串中全部的匹配子串,並且沒有index和input屬性。

  1. String.protatype.split(reg):
    以reg爲界限將字符串分割爲一個字符串數組。

  2. String.protatype.replace:
    將一個字符串中的一部分替換成另外一個字符串。

    • String.protatype.replace(str, replaceStr)
    • String.protatype.replace(reg, replaceStr)
    • String.protatype.replace(reg, function)
      function中參數的定義:
      1. 匹配的字符串
      2. 正則表達式分組的內容,沒有分組則沒有該參數
      3. 匹配項在字符串中的index
      4. 原字符串
1 'a1b2c3d4e5'.replace(/(\d)(\w)(\d)/g, function(match, group1, group2, group3, index, origin){
2      return parseInt(group1) + parseInt(group3);
3  });

 

 

5. 正則表達式示例

正則表達式 描述
/\b([a-z]+) \1\b/gi 一個單詞連續出現的位置。
/(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/ 將一個URL解析爲協議、域、端口及相對路徑。
/^(?:Chapter|Section) [1-9][0-9]{0,1}$/ 定位章節的位置。
/<\s*(\S+)(\s[^>])?>[\s\S]<\s*\/\1\s*>/ 匹配 HTML 標記。
/^(((13|15|18)[0-9])|14[57]|17[0134678])\d{8}$/ 匹配手機號碼
/^\w+((-\w+)|(.\w+))\@[A-Za-z0-9]+((.|-)[A-Za-z0-9]+).[A-Za-z0-9]+$/ 匹配郵箱
/(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/ 匹配身份證號
相關文章
相關標籤/搜索