正則表達式詳解

正則表達式是一個很是有用的用來匹配驗證字符串的工具。不少人以爲正則表達式規則繁多,學了也會忘記,不如等到須要使用的時候再去查閱便可。這樣的觀點也無可厚非,不過我曾經看到過一個絕妙的關於閱讀的比喻,閱讀就像是將竹簍浸入到水裏面,雖然撈打上來的時候竹簍裏並無裝水,可是竹簍已經被浸溼了。學習正則表達式也是如此,按部就班,方能厚積薄發。javascript

大綱

◆ 經常使用的正則表達式java

◆ 分組捕獲與後向引用正則表達式

◆ 貪婪模式與非貪婪模式工具

◆ 應用場景學習

經常使用的正則表達式

1.元字符

元字符 釋義
普通字符 如A-Z、a-z、0-9 等等
. 除換行之外的其餘任意字符, 若是須要匹配換行符,可用[.n]
s 空白字符
S 除空白字符之外的任意字符
w 字母、數字、下劃線
W 除了字母、數字、下劃線之外的任意字符
d 數字 0-9
D 除了數字以外的任意字符
^ 匹配輸入字符串開始的位置
$ 匹配輸入字符串結尾的位置
b 單詞邊界,匹配一個完整的單詞可使用 bwordb

以上是最經常使用的正則表達式匹配字符,固然,還有不少其餘的匹配元字符,好比\t匹配製表符,\r匹配回車符,\n匹配換行符等。spa

\d爲例,\d表明數字0-9,等價於字符組[0-9]code

例:匹配字符串 ‘fefafe332gt66ooj44nie85kk’ 中的全部數字
var str = 'fefafe332gt66ooj44nie85kk'
var reg = /\d+/g
console.log(str.match(reg)) // 結果爲["332", "66", "44", "85"]

2.限定符

限定符 釋義
* 0到無數次。例如,zo* 能匹配 "z" 以及 "zoo"
+ 1到無數次。例如,zo+ 不能匹配 「z」 可是能匹配 「zo」和「zoo」
? 0 或者1 次。例如,zo? 能匹配 「z」和 「zo」 可是不能匹配 「zoo」
{n} 匹配肯定的N次。 例如, zo{2} 只能匹配到 zoo
{n,} 匹配n到無限次。 例如,zo{1,} 不能匹配「z」 可是能匹配「zo」和「zoo」
{n,m} 匹配n到m次。注意:在逗號和兩個數之間不能有空格

以上這些限定符,能夠匹配指定個數的字符,在可以匹配的範圍以內,儘量多的匹配。其中{n,m}限定符有兩個注意點:ip

  1. n不能大於m
  2. 在逗號和兩個數之間不能有空格,不然沒法匹配
例:匹配38到288之間的數
let reg = /\b((38|39)|([4-9]\d)|(1\d{2})|(2[0-7]\d)|(28[0-8]))\b/g
let str = '45 454 255 288 38 88 11 37 100 109 28 000 289 209'
console.log(str.match(reg)) // ["45", "255", "288", "38", "88", "100", "109", "209"]

3.修飾符

修飾符 釋義
g global 全局搜索 (不添加 搜索到第一個匹配中止)
i ignore case 忽略大小寫
m multiline 多行匹配

m多行匹配用得相對較少,可是也有必定用處。內存

例:對比m和mg
var str8 = "abeifenabc\nabpheeabc" 
var reg8a = /^ab/gm
var reg8b = /^ab/g
console.log(str8.match('gm:'+reg8a)) // 結果爲:["ab", "ab"]
console.log(str8.match('g:'+reg8b)) // 結果爲:["ab"]

上面三個修飾符最經常使用。固然,還有其餘修飾符,好比A表示強制從目標字符串開頭匹配,x表示將模式中的空白忽略。字符串

4.其餘

經常使用符號 釋義
分支符號"\ " 用來匹配指定幾個規則中的一個
轉義符號"\" 用於匹配"[""^""+"")"等有特殊含義符號
字符組 [] 用於匹配指定範圍以內的任意一個字符

例如:表達式 [cChH]at 能夠只能匹配到 catCathatHat 四個字符串中的一個

例:敏感詞過濾。好比:「我草你媽哈哈背景天胡景濤哪肉涯剪短髮慾望」,過濾:'草肉慾胡景濤'
let str9 = '我草你媽哈哈背景天胡景濤哪肉涯剪短髮慾望';
let regExp = /草|肉|欲|胡景濤/g;
let result = str9.replace(regExp, function(match) {
    let len = match.length;
    let str;
    switch (len) {
        case 1:
            str = '*';
            break;
        case 2:
            str = "**";
            break;
        case 3:
            str = "***";
            break;
        default:
            str = '****';
    }
    return str;
});
console.log(result); //我*你媽哈哈背景天***哪*涯剪短髮*望

分組捕獲與後向引用

1.分組捕獲

當咱們想要匹配多個字符的時候,可使用限定符來指定個數,那當咱們須要匹配多個字符串的狀況,該怎麼辦呢?可使用分組捕獲

  • 概念:

分組捕獲是指將想要匹配的正則表達式用小括號括起來,而後與限定符組合使用,能夠連續匹配符合規則的字符串。每個小括號表明的表達式分爲一組,做爲子表達式,後期能夠經過捕獲不一樣組的內容來進行替換等操做。

例:匹配字符串isuwang連續出現3次的狀況

isuwang{3} isuwang1

(isuwang){3} isuwang2

能夠看到,下面一組例子將isuwang字符串看成一個組,總體匹配了3次。

2.非捕獲分組

  • 分組捕獲的缺點:

有些不得不用()可是後期又不會用到的子表達式內容,記錄在組裏面會佔用內存,下降匹配效率

  • 解決:

使用非捕獲組。只進行分組,並不將子表達式匹配到的內容捕獲到組裏。

字符 描述 示例
(?:pattern) 匹配pattern,但不捕獲匹配結果。 ‘industr(?:y\ ies)匹配'industry'或'industries'
(?=pattern) 零寬度正向預查,不捕獲匹配結果。 'Windows (?=95\ 98\ NT\ 2000)'匹配 "Windows2000" 中的 "Windows",不匹配 "Windows3.1" 中的 "Windows"。
(?!pattern) 零寬度負向預查,不捕獲匹配結果。 'Windows (?!95\ 98\ NT\ 2000)'匹配 "Windows3.1" 中的 "Windows"不匹配 "Windows2000" 中的 "Windows"。
(?<=pattern) 零寬度正向回查,不捕獲匹配結果。 '2000 (?<=Office\ Word\ Excel)'匹配 " Office2000" 中的 "2000",不匹配 "Windows2000" 中的 "2000"。
(?<!pattern) 零寬度負向回查,不捕獲匹配結果。 '2000 (?<!Office\ Word\ Excel)'匹配 " Windows2000" 中的 "2000",不匹配 " Office2000" 中的 "2000"。
  • 使用狀況:

通常只有在比較複雜,「()」使用較多的狀況下會考慮使用非捕獲組。好比驗證日期的正則表達式。

  • 對比:

未使用非捕獲組的正則

^((?!0000)[0-9]{4}-((0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-8])|(0[13-9]|1[0-2])-(29|30)|(0[13578]|1[02])-31)|([0-9]{2}(0[48]|[2468][048]|[13579][26])|(0[48]|[2468][048]|[13579][26])00)-02-29)$

使用了非捕獲組的正則:

^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$

3.後向引用

  • 做用:

後向引用用於重複搜索前面某個分組匹配的文本。例如,\1 表明分組1匹配的文本,也能夠用$1來表示

  • 說明:

子分組捕獲的內容可在正則表達式裏面或者其餘文本里面做進一步的處理。默認狀況下,從左向右,以分組的左括號爲標誌,第一個出現的分組的組號爲1,第二個爲2,以此類推。也可使用命名分組的方式,對每一個分組進行命名。

例:檢查重複字符串\
給定字符串 str,檢查其是否包含連續重複的字母(a-zA-Z),包含返回 true,不然返回false
let str4 = 'abccdefgjhiss'
let reg4a = /([a-zA-Z])\1/g
let reg4b = /([a-zA-Z]){2}/g
console.log(str4.match(reg4a)) // ["cc", "ss"]
console.log(str4.match(reg4b)) // ["ab", "cc", "de", "fg", "jh", "is"]

4.貪婪模式和非貪婪模式

  • 貪婪模式:

在整個表達式匹配成功的前提下,儘量多的匹配

  • 非貪婪模式:

整個表達式匹配成功的前提下,儘量少的匹配。非貪婪模式只被部分NFA引擎所支持。

  • 量詞:
貪婪模式 非貪婪模式
{m,n} {m,n}?
{m,} {m,}?
? ??
* *?
+ +?
例子:
提取兩個""中的子串,其中不能再包含""\
字符串:"The colleagues in "kuaisuwang" are very "diligent" and united"

錯誤解法(經過非貪婪匹配)

let str6='"The colleagues in "isuwang" are very "diligent" and united"'
let reg6a=/".*?" /g // 注意"後面還有個空格
console.log(str6.match(reg6a)) //  [""The colleagues in "isuwang" ", ""diligent" "]

正確解法(經過貪婪模式匹配)

let str6='"The colleagues in "isuwang" are very "diligent" and united"'
let reg6b=/"[^"]*" /g // 注意"後面還有個空格
console.log(str6.match(reg6b)) //[""isuwang" ", ""diligent" "]

總結

此篇文章主要講述了經常使用的正則表達式符號,以及分組和後向引用,貪婪模式和非貪婪模式兩種模式,這些知識點呢,在工做當中會很是有用。至於正則表達式在我工做中的運用,我放在下一篇來跟你們進行分享。

相關文章
相關標籤/搜索