咱們知道,在正則表達式中,可使用[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,而且記錄下這個狀態。
...
輪到字符',.*能夠匹配',也能夠不匹配,但使用了匹配優先量詞*,全部.*會嘗試先匹配',而且記錄下這個狀態。
最後是字符串末尾的",.*能夠匹配",也能夠不匹配,但使用了匹配優先量詞*,全部.*會嘗試先匹配",而且記錄下這個狀態。
這個時候,字符串後面已經沒有字符了,可是正則表達式中仍是有"沒有匹配,因此只能查看以前保存的備用狀態,看看能不能回退幾步,以便匹配",因而讓.*後退幾步,以便讓"能夠匹配",發現正好能夠匹配,因此整個匹配宣告結束,這個「反悔」的過程,專業術語叫回溯。字符串
忽略優先量詞,與匹配優先量詞相反,在不肯定是否匹配某個字符時,會優先選擇「不匹配」的狀態,在嘗試匹配表達式以後的字符,若是匹配失敗,則再回溯,選擇以前保存的「匹配的」狀態,這樣保證了匹配的正確性。
只須要把.*改成.*?便可變成忽略優先量詞。
具體過程: 相似於匹配優先量詞
這種匹配能夠用於完成不少功能,好比匹配註釋,標籤等。
匹配優先量詞 | 忽略優先量詞 |
---|---|
* | *? |
+ | +? |
? | ?? |
{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個及以上)的橫線