正則表達式之量詞

  咱們知道,在正則表達式中,可使用[0-9]或\d來匹配單個數字字符,可是,若是須要驗證一個更復雜的字符串呢,好比大陸地區的郵政編碼。
  不過郵政編碼並無特別規定,只有由6個數字組成的字符串而已, 如246512,根據[0-9]或\d,咱們能夠很快的實現匹配的正則表達式,\d\d\d\d\d\d。
  從上能夠看出,咱們重複用了6個單個字符來實現匹配,因爲目前數字較少,看着還能夠接受,那若是不是6個數字組成的,10個?20個?甚至是更多呢,顯然這種方式是不行的,正則表達式提供了量詞,用來限定出現的次數,能夠很好解決這個問題。javascript

首先,看下量詞的表示形式:java

量詞的通常形式

表:通常形式

量詞 說明
{n} 量詞前面的元素必須出現n次
{n,m} 量詞前面的元素至少出現n次,最多出現m次
{n,} 量詞前面的元素至少出現n次,無上限
{,m} 量詞前面的元素能夠不出現,也能夠出現,最多出現m次(javascript不支持這種寫法)
/^[0-9]{2}$/.test('12') // => true
    /^[0-9]{2}$/.test('123') // => false
    /^[0-9]{2,5}$/.test('123') // => true
    /^[0-9]{2,5}$/.test('123456') // => false
    /^[0-9]{2,}$/.test('123456') // => true
    /^[0-9]{0,5}$/.test('123456') // => false
    /^[0-9]{0,5}$/.test('12') // => true
    /^[0-9]{0,5}$/.test('') // => true

注意:

一、{n,m}之間的逗號後面不能出現空格,不然沒法正確匹配。</font>正則表達式

/^[0-9]{0, 5}$/.test('12') // => false

二、量詞限定的出現次數通常都有明確下限,若是沒有,則默認爲0,因此推薦{,m}寫成{0,m},這是通用的寫法。bash

/^[0-9]{,5}$/.test('12') // => false

經常使用量詞

{n,m}是通用形式的量詞,正則表達式還有3個經常使用的量詞,分別是+、?、*,雖然形式不一樣於{n,m},但功能確實相同的,能夠看成是「量詞的簡介法」。編碼

表:經常使用量詞

經常使用量詞 {n,m}等價形式 說明
* {0,} 可能出現,也可能不出現,出現次數沒有上限
+ {1,} 至少出現次數爲1,出現次數沒有上線
? {0,1} 最多出現1次,有可能不出現(出現0次或1次)
/^\d+(\.\d+)*$/.test('123') // => true
   /^\d+(\.\d+)*$/.test('123.123') // => true
   /^\d+(\.\d+)*$/.test('123.123.111') // => true
   /^\d+(\.\d+)*$/.test('123.') // => false
   /^travell?er$/.test('traveller') // => true
   /^<[^>]+>$/.test('<div>') // => true
   /^<[^>]+>$/.test('<b>') // => true
   /^<[^>]+>$/.test('<>') // => false
   /^travell?er$/.test('traveler') // => true
   /^travell?er$/.test('traveller') // => true

在實際開發中,不少狀況用這三種表示形式幾乎能夠知足,所以使用頻率要高於{n,m}。spa

點號

正則中,有一個特殊的特殊的元字符,點號.,它能夠匹配任意字符,除了換行符(\n)。
若是須要用點號匹配任意字符,則必須在單行內匹配,或者使用其餘的方式來替代,如[\s\S]、[\w\W]或[\d\D]。
但在實際開發中,許多人爲了圖省事,不少狀況下會這樣使用,這樣濫用點號將會帶來一些問題。code

如:ip

new RegExp("^.*$").exec("quoted 'string '")
    new RegExp("^(([a-z]+)\\s')+$").exec("quoted 'string '")

如上,匹配的結果將會是整個字符串:"quoted 'string '",這就是咱們常說的貪婪模式。
要弄清楚爲何會是這個結果,則必須瞭解表達式的匹配原理,以".*"爲例。
在正則表達式中,點號.能夠用來匹配除了換行符以外的全部字符,而*表示匹配的字符串長度沒有限制,因此在".*"匹配過程當中,每遇到一個字符, ".*"均可以匹配,究竟是匹配它,仍是忽略它,將其留給最後的"來匹配呢?
答案是由量詞來決定的,在正則表達式中量詞分爲幾類,匹配優先量詞(貪婪量詞)和忽略優先量詞(惰性量詞)(還有一種支配量詞,這裏就不介紹了,請自行百度)開發

匹配優先量詞

匹配優先量詞,顧名思義,在拿不許是否匹配某個字符時,優先嚐試匹配,而且記下這個狀態,以備未來「反悔」。
具體過程:
一開始,"匹配",而後到字符q,.*能夠匹配q,也能夠不匹配,但使用了匹配優先量詞*,全部.*會嘗試先匹配q,而且記錄下這個狀態。
接下來是字符字符u,.*能夠匹配u,也能夠不匹配,但使用了匹配優先量詞*,全部.*會嘗試先匹配u,而且記錄下這個狀態。
...
輪到字符',.*能夠匹配',也能夠不匹配,但使用了匹配優先量詞*,全部.*會嘗試先匹配',而且記錄下這個狀態。
最後是字符串末尾的",.*能夠匹配",也能夠不匹配,但使用了匹配優先量詞*,全部.*會嘗試先匹配",而且記錄下這個狀態。
這個時候,字符串後面已經沒有字符了,可是正則表達式中仍是有"沒有匹配,因此只能查看以前保存的備用狀態,看看能不能回退幾步,以便匹配",因而讓.*後退幾步,以便讓"能夠匹配",發現正好能夠匹配,因此整個匹配宣告結束,這個「反悔」的過程,專業術語叫回溯。字符串

表達式".*"對字符串"quoted 'string '"的匹配過程

忽略優先量詞

忽略優先量詞,與匹配優先量詞相反,在不肯定是否匹配某個字符時,會優先選擇「不匹配」的狀態,在嘗試匹配表達式以後的字符,若是匹配失敗,則再回溯,選擇以前保存的「匹配的」狀態,這樣保證了匹配的正確性。
只須要把.*改成.*?便可變成忽略優先量詞。
具體過程: 相似於匹配優先量詞
這種匹配能夠用於完成不少功能,好比匹配註釋,標籤等。

表:匹配優先量詞與忽略優先量詞

匹配優先量詞 忽略優先量詞
* *?
+ +?
? ??
{n} {n}?
{n,m} {n,m}?
{n,} {n,}?
{,m} {,m}?

轉義

在正則表達式中,+、?、*等量詞是特殊字符,具備特殊含義,可是有些狀況下,只想表達字符自身,則須要轉義,即在字符前加反斜線。對於通常形式的量詞{n,m},雖然含有特殊含義的字符不止一個,但轉義時只須要給{添加反斜線便可,如須要匹配{n,m},則是{n,m}。
注意:忽略優先字符不像通常形式字符{n,m}同樣,只須要添加一個反斜線,如*?,必須都要添加反斜線,即正則表達式必須寫做:*?,而不是*?,後者的意思是「*這個字符有可能出現,有可能不出現」。

表:各類量詞的轉義

量詞 轉義形式
* *
+ +
? ?
*? *?
+? +?
?? ??
{n} {n}
{n,m} {n,m}
{n,} {n,}
{,m} {,m}

除此以外,元字符點.也須要加反斜線來進行轉義。
因爲點.表示除了換行符以外的字符,也包括點號(.),因此不少人忽略了對其轉義,但若是忽略了對其轉義,則在嚴格匹配點號時會出錯。好比匹配小數(3.14)、IP地址(192.168.1.1)、Email地址(some@host.com)等,因此如果要匹配的文本包含點號,必定不要忘了對其進行轉義,不然會出現以下的出錯:

/^\d+.\d+$/.test("3.14") // => true
    /^\d+.\d+$/.test("3@14") // => true

    /^\d+\.\d+$/.test("3.14") // => true
    /^\d+\.\d+$/.test("3@14") // => false

正則分析

一、密碼長度在6-12個字符之間二、只能由小寫字母,數字和橫線組成三、開頭和結尾不能爲橫線四、不能所有爲數字五、不容許有連續(2個及以上)的橫線

相關文章
相關標籤/搜索