正規表示式基礎入門

ACodingIceBear發表於2017-12-22

概述

正規表示式是一種被用於匹配字串的字元匹配模式。多用於表單驗證。正規表示式:regular expression,簡稱RegExp。

建立正規表示式最簡單的方式使用正則字面量。

字面量:用兩個/做界定符。一般會將字面量賦值給一個變數。

var pattern = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;

正規表示式可以使用一些字串方法或正則方法進行操作:

字串的方法:

  • split()根據匹配字串切割父字串,返回子串組成的陣列。
  • match()使用正規表示式與字串相比較,返回一個包含匹配結果的陣列。
  • search()對正規表示式或指定字串進行搜尋,返回第一個出現的匹配項的下標。
  • replace()用正規表示式和字串直接比較,然後用新的子串來替換被匹配的子串,返回新的匹配之後的字串。

正規表示式方法:

  • exec()在目標字串中執行一次正則匹配操作,返回的是第一次匹配的子串的陣列。
  • test()測試當前正則是否能匹配目標字串,返回true或false。

不同的資料型別又自己的方法和屬性,使用時必須呼叫正確,下面分別介紹幾種方法的使用。

字串方法

  • plit()根據匹配字串切割原字串。split方法傳遞的引數是分隔符,可以是str或者reg,找到分隔符之後就從str中刪除,返回子串陣列。

如果沒有找到分隔符,那麼返回的陣列包含的是一整個str組成元素的陣列。如果分隔符為空字串“”,返回的是字串每個字元組成元素的陣列。 返回值:由切割後的子字串組成陣列。可以用來將使用者輸入的不規範的字串轉為正確的Array。

例:根據空格切割字串:'aa bbb c dd eeeeee'

'aa bbb    c dd eeeeee'.split(/\s+/);   //["aa","bbb","c","dd","eeeeee"]
複製程式碼

\s:表示空白字元;

+:表示前面的一個符號代表的字元可以出現一次或者多次

  • earch()對正規表示式或指定字串進行搜尋,傳入的引數是字串或者reg,返回第一個出現的匹配項的下標(類似indexOf)。

返回值:子串或正則匹配結果在父字串中的第一次出現的位置的下標。search搜尋只找到第一次搜尋到的位置下標,所以全域性標誌也就不起作用了。如果匹配的子串在父字串中沒有對應的字元,返回結果就是-1.(可以利用search匹配字串有無在表格中進行關鍵字搜尋,條件判斷是看是否等於-1)

function withSearch(str){
            var newStr = "";
            for(var i =0; i<str.length; i++){
                if(newStr.search(str[i]) == -1){
                    newStr += str[i];
                }
            }
            return newStr;
        }
        console.log(withSearch('abcdde'));     //abcde
複製程式碼
  • match()使用正規表示式與字串相比較,接受引數只有一個要麼是正規表示式,要麼是reg物件,返回一個包含匹配結果的陣列。本質上和呼叫正則的exec方法相同。

返回值:是由匹配結果組成的陣列。和split一樣返回的是陣列,但是match返回的是第一個匹配的子串,不過可以應用全域性標誌g,搜尋全部。

在 'abbcccbbbbbddbbbdabbb' 中查詢重複 'b' 字串

'abbcccbbbbbddbbbdabbb'.match(/b+/);     //['bb']
複製程式碼
  • replace()用正規表示式和字串直接比較,然後用新的子串來替換被匹配的子串。 引數:傳遞兩個引數,第一個是正則或匹配的字串,第二個是要替換的新的內容或者函式。

返回值:是一個新的字串,原始字串不發生變化。如果第一個引數是字串,那麼只會替換第一個子字串;想要替換所有子串,只有一個辦法就是傳入reg,同時指定g標誌。

例:過濾字串中空格:'aa b c d e f ' => "aabcdef" 使用全域性界定符g進行全域性匹配和替換。

str.replace(/\s+/g, ‘’);      //用空字串替換匹配的空白
複製程式碼

正則方法

  • exec()在字串中尋找匹配字串,並返回一個包含匹配結果的陣列。返回的陣列很特別的帶了兩個屬性,可以通過呼叫index屬性和input屬性檢視匹配的子串在字串中的位置,而input表示應用reg的字串。

引數:要查詢的字串。

exec方法即使在模式中設定了全域性標誌g,每次也只會返回一個匹配項。在不設定g時,同一個str上多次呼叫exec()都始終返回第一個匹配項;而設定了g,每次呼叫exec()都會在字串中繼續查詢新的匹配項,知道搜尋到字串末尾為止。lastIndex在全域性模式下回隨著呼叫而改變++。《高階程式設計》

  • test() 檢測字串是否匹配正規表示式,傳入的引數是字串,如果字串中有正則匹配的就返true。 正規表示式中如果沒有限制開頭也沒有限制結尾,只要字串中包含正則匹配的部分,就會返回一個true的值,否則返回false。

test方法經常用在if判斷語句中作為條件來使用。

判斷'aaddccddabcddeeddfff'是否包含'abc'字串

/abc/.test('aaddccddabcddeeddfff');  //true
複製程式碼

正規表示式的術語和操作符

正規表示式的組成:由一些普通字元和一些特殊字元(又叫元字元--metacharacters)組成。普通字元包括大小寫的字母和數字,而元字元則具有特殊的含義。 特殊字元: javascript中常用正則的特殊字元有

( ) [ ] { } \ ^ $ | ? * + . 若想匹配這類字元必須用轉移符號 \ 如:\(,\^,\\

  • 精確匹配

正規表示式中是一些普通字元組成,在進行字串匹配時,需要進行精確匹配,比如/good/,匹配時,字串中必須包含g,o,o,d四個字元,而且順序不能發生變化,中間也不允許出現其他字元,也就是說必須包含”good”字串。

  • 預定義特殊字元

預定義特殊字元:

\t /\t/製表符,縮排 eg: console.log(/\t/.test('’)),表示匹配一個縮排或製表符

\n /\n/回車符 eg: console.log(/\n/.test(aaabbb)); ,表示匹配一個回車換行

問題:""不能包裹一個包含回車換行的字串。

解決方法:將引號換成數字1前面的``引號,就可以包括回車。 \f /\f/換頁符 \b /\b/空格,表示匹配的是一個空格,\b可以搭配字元匹配作為邊界的查詢識別符號,在邊界處詳細講。

  • 字符集
    字符集:表示一類中任何一個字元都可以匹配,核心是[]類對應的是一個字元。 字符集寫法:[一類字元]

簡單類:正則的多個字元對應一個字元,我們可以用[]把它們括起來,讓[]這個整體對應一個字元 o[abc]z →oaz,obz,ocz

範圍類:有時匹配的東西過多,而且型別又相同,全部輸入太麻煩,我們可以在中間加了個橫線。 [a-z]、[0-9]、[A-Z]

組合類:允許用中括號匹配不同型別的單個字元[a-zA-Z0-9] [a-zA-Z_$][a-zA-Z0-9_$] 變數名的命名規則 [0-9a-z]:表示可以匹配小寫字母或者數字。

負向類:[]內部最前面加個元字元^進行取反,表示匹配不能為括號裡面的字元。 [^a]:表示只要不是a都能匹配成功。

  • 修飾符

g 全域性修飾符,再查詢時不會找到第一次結果後就結束,而是在找到全域性範圍內所有結果後再結束。 global:全球的、全域性的。 書寫位置:在正則符號的後面//g.

i 修飾符用於執行對大小寫不敏感的匹配。case-insensitive 書寫位置:在正則符號的後面//i

m表示多行模式,忽略換行。

  • 邊界

^開頭注意不能緊跟於左中括號的後面 書寫位置:寫在//正則符號內部的開始位置,表示後面的字元必須匹配成功,而且需要作為字串的開頭。

$結尾 書寫位置:寫在//正則符號內部的結束位置,表示$前面的字元必須匹配成功,而且需要作為字串的結束。

綜合使用^和 $,分別界定字串的開頭和結尾,表示中間部分的字元必須匹配成功,而且所有字元必須位於開頭,也必須位於結尾。也就是說中間的部分就是字串的全部。

\b單詞邊界,用於查詢位於單詞的開頭或結尾的匹配。區間比^$要小,只作用在單詞。 \b會搭配其他字元進行匹配,其他字元必須先匹配成功,如果\ba,要先匹配一個a字元,還要求a位於一個單詞的開始位置,如果c\b,表示要匹配一個c字元,還要求c必須位於一個單詞的結尾。

如果前後都有\b,表示內部匹配的結果必須是一個單獨的完整的單詞。

\B非單詞邊界,用於查詢不處在單詞的開頭或結尾的匹配。 \B也要搭配其他符號進行匹配,表示前面後後面的匹配的字元,除了要匹配成功之外,還不能位於一個單詞的開頭或結尾。

  • 預定義類

本質就是將最常用的一些特殊類的字符集進行一個簡化書寫。

[^\n\r]除了換行和回車之外的任意字元 匹配:除了回車和換行之外其他所有字元,比如數字、字母、漢字、特殊符號、空格、縮排等。

\d[0-9]數字字元(digital) 匹配:匹配一個任意的數字字元。

\D[^0-9]非數字字元 匹配:非數字字元,只要不是數字都能匹配成功

\s[ \t\n\x0B\f\r]空白字元(space) 匹配:可以匹配所有的空白,包括縮排、回車、換行、空格、換頁。

\S[^ \t\n\x0B\f\r]非空白字元 匹配:表示所有非空白的字元,除了空白都能匹配。

\w[a-zA-Z_0-9]單詞字元(所有的字母/數字/下劃線) 匹配:所有的字母(大小寫)、數字、下劃線。

\W[^a-zA-Z_0-9]非單詞字元 匹配:除了數字、字母、下劃線,其他都能匹配。

  • 量詞

有時會遇到某個正則符號需要連續匹配多次,可以利用量詞進行次數描述。 使用{}包裹數字,表示前面的一個字元可以出現多少次。

{n}硬性量詞對應零次或者n次 表示:n是幾,前面的符號需要連續出現對應的幾次。

{n,m}軟性量詞至少出現n次但不超過m次(中間不能有空格) 表示:前面的字元必須出現至少n次,最多不超過m次。

{n,}軟性量詞至少出現n次(+的升級版) 表示:前面的字元可以出現n次及以上。

?{0,1}軟性量詞出現零次或一次

*{0,}軟性量詞出現零次或多次(任意次)

+{1,}軟性量詞出現一次或多次(至少一次)

量詞只能修飾前面的一個字元,不能直接修飾前面多個字元,想要操作多個要把想操作的字串用小括號括起來。

  • 或操作符

可以使用豎線(|)字元表示或者的關係。 如果沒有任何限制的情況下,或操作符會將整體正規表示式分成兩部分。 只要有一種情況匹配成功都能返回true。

如果我們想匹配a和c中匹配d或b,需要將d和b的或關係放在小括號內,縮小或操作符的範圍。

  • 分組

雖然量詞的出現,能幫助我們處理一排密緊密相連的同型別字元。但這是不夠的,我們用中括號表示範圍內選擇,大括號表示重複次數。如果想獲取重複多個字元,我們就要用小括號進行分組了。 使用小括號分組後,就可以對內部字元進行整體的控制。

  • 分組的反向引用

反向引用標識是對正規表示式中的匹配組捕獲的子字串進行編號,通過“\編號(在表示式中)”,“$編號(在表示式外)”進行引用。從1開始計數。

正則中如果有小括號的分組,會在字串中找到匹配的子字串,可以將子字串結果拿到正則中進行二次使用,或者正規表示式之外進行二次呼叫。 正規表示式中有多個小括號的話,按照編號1,2,3……進行編號,從左往右。exec test str的replace都可以使用這種方法

正則中:使用\1,反向使用子串1的結果。

正則外面:使用$1,反向使用子串1的結果。

字串的replace方法的反向引用。 第一個引數:正規表示式,內部有小括號的話,可以進行編號,按順序小括號分別對應第一小組,第二小組...。 第二個引數:可以利用分組匹配結果,進行反向引用。

更常用的方式,給replace第二個引數設定為一個替換函式。

注意:

1.函式的引數位置,第一個必須寫match,後面的引數可以使用反向引用的編號$,$2……

2.函式必須有返回值,返回值的結果才是替換字串的內容。

應用:找出字串中最長的重複子串

 function demo(str) {
        var arr = str.split(''); //把字串轉換為陣列
        str = arr.sort().join(''); 

        var value = ‘’;     //用來存放出現最多的substr的中間變數
        var index = 0;     //用來存放最大長度
            
       var re = /(\w)\1+/g; //
           
        str.replace(re, function ($0, $1) {
            //alert($0); 代表每次匹配成功的結果 : aa dd jj kk l sssssssssssssssss
            //alert($1); 代表每次匹配成功的第一個子項,也就是\w: a d j k l s 

        if (index < $0.length) { //如果index儲存的值小於$0的長度就進行下面的操作
            index = $0.length; // 這樣index一直儲存的就在最大的長度
            value = $0; //value儲存的是出現最多的這個字元
        }
    });
        alert('最多的字元:' + value + ',重複的次數:' + index); 
    }
複製程式碼
  • 中文字元

匹配中文:[\u4e00-\u9fa5]

常用正規表示式

網上的一些常用方法

  • 使用者名稱:4-16位,字母、數字、下劃線、減號. 同時包括的內容可以通過放到一個類中,+進行多次選擇。
 var pattern = /^[a-zA-Z0-9_-]{4,16}$/;
複製程式碼
  • 密碼強度:最少6位,包括1個大寫字母,1個小寫,1個數字,1個特殊符號
var pattern = /^.*(?=.{6,})(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*? ]).*$/;
複製程式碼

(?<= )是連在一起的格式,不要把=單獨拿出。與之對應的格式是(?<! )。

(?<=\s*)\d+ 匹配的是 "abc 123abc""abc123abc"中的"123" 匹配的是:前面有"重複0次或多個空格"後面緊跟的是數字的數字部分; 注:匹配的字串只有\d+,不包括\s*

(?=exp)也叫零寬度正預測先行斷言,它斷言自身出現的位置的後面能匹配表示式exp。 比如\b\w+(?=ing\b),匹配以 ing 結尾的單詞的前面部分(除了 ing 以外的部分),如查詢 I'm singing while you're dancing.時,它會匹配 sing 和 danc。 (?<=exp)也叫零寬度正回顧後發斷言,它斷言自身出現的位置的前面能匹配表示式 exp。比如(?<=\bre)\w+\b 會匹配以re開頭的單詞的後半部分(除了 re以外的部分),例如在 查詢reading a book時,它匹配ading。 假如你想要給一個很長的數字中每三位間加一個逗號(當然是從右邊加起了), 你可以這 樣查詢需要在前面和裡面新增逗號的部分:((?<=\d)\d{3})*\b,用它對 1234567890 進行查 找時結果是234567890。 下面這個例子同時使用了這兩種斷言:(?<=\s)\d+(?=\s)匹配以空白符間隔的數字(再次 強調,不包括這些空白符)

  • 數字:^[0-9]+$

  • n位的數字:^\d{n}$

  • 至少n位的數字:^\d{n,}$

  • m-n位的數字:^\d{m,n}$

  • 零和非零開頭的數字:^(0|[1-9][0-9]*)$

  • 非零開頭的最多帶兩位小數的數字:^([1-9][0-9]*)+(.[0-9]{1,2})?$

  • 帶1-2位小數的正數或負數:^(-)?\d+(.\d{1,2})?$

  • 正數、負數、和小數:^(-|+)?\d+(.\d+)?$

  • 有兩位小數的正實數:^[0-9]+(.[0-9]{2})?$

  • 有1~3位小數的正實數:^[0-9]+(.[0-9]{1,3})?$

  • 非零的正整數:^[1-9]\d*$ 或 ^([1-9][0-9]){1,3}$ 或 ^+?[1-9][0-9]$

  • 非零的負整數:^-[1-9][]0-9"$ 或 ^-[1-9]\d$

  • 非負整數:^\d+$ 或 ^[1-9]\d*|0$

  • 非正整數:^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$

  • 非負浮點數:^\d+(.\d+)?$ 或 ^[1-9]\d*.\d*|0.\d*[1-9]\d*|0?.0+|0$

  • 非正浮點數:^((-\d+(.\d+)?)|(0+(.0+)?))$ 或 ^(-([1-9]\d*.\d*|0.\d*[1-9]\d*))|0?.0+|0$

  • 正浮點數:^[1-9]\d*.\d*|0.\d*[1-9]\d*$ 或 ^(([0-9]+.[0-9][1-9][0-9])|([0-9][1-9][0-9].[0-9]+)|([0-9][1-9][0-9]))$

  • 負浮點數:^-([1-9]\d*.\d*|0.\d*[1-9]\d*)$ 或 ^(-(([0-9]+.[0-9][1-9][0-9])|([0-9][1-9][0-9].[0-9]+)|([0-9][1-9][0-9])))$

  • 浮點數:^(-?\d+)(.\d+)?$ 或 ^-?([1-9]\d*.\d*|0.\d*[1-9]\d*|0?.0+|0)$

  • 漢字:^[\u4e00-\u9fa5]{0,}$

  • 英文和數字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$

  • 長度為3-20的所有字元:^.{3,20}$

  • 由26個英文字母組成的字串:^[A-Za-z]+$

  • 由26個大寫英文字母組成的字串:^[A-Z]+$

  • 由26個小寫英文字母組成的字串:^[a-z]+$

  • 由數字和26個英文字母組成的字串:^[A-Za-z0-9]+$

  • 由數字、26個英文字母或者下劃線組成的字串:^\w+$ 或 ^\w{3,20}$

  • 中文、英文、數字包括下劃線:^[\u4E00-\u9FA5A-Za-z0-9_]+$

  • 中文、英文、數字但不包括下劃線等符號:^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$

  • 可以輸入含有^%&',;=?$"等字元:[^%&',;=?$\x22]+

  • 禁止輸入含有~的字元:[^~\x22]+

  • Email地址:^\w+([-+.]\w+)@\w+([-.]\w+).\w+([-.]\w+)*$

  • 域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?

  • InternetURL:[a-zA-z]+://[^\s]* 或 ^http://([\w-]+.)+[\w-]+(/[\w-./?%&=]*)?$

  • 手機號碼:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$

  • 電話號碼("XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX):^((\d{3,4}-)|\d{3.4}-)?\d{7,8}$

  • 國內電話號碼(0511-4405222、021-87888822):\d{3}-\d{8}|\d{4}-\d{7}

  • 身份證號(15位、18位數字):^\d{15}|\d{18}$

  • 短身份證號碼(數字、字母x結尾):^([0-9]){7,18}(x|X)?$ 或 ^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$

  • 帳號是否合法(字母開頭,允許5-16位元組,允許字母數字下劃線):^[a-zA-Z][a-zA-Z0-9_]{4,15}$

  • 密碼(以字母開頭,長度在6~18之間,只能包含字母、數字和下劃線):^[a-zA-Z]\w{5,17}$

  • 強密碼(必須包含大小寫字母和數字的組合,不能使用特殊字元,長度在8-10之間):^(?=.\d)(?=.[a-z])(?=.*[A-Z]).{8,10}$

  • 日期格式:^\d{4}-\d{1,2}-\d{1,2}

  • 一年的12個月(01~09和1~12):^(0?[1-9]|1[0-2])$

  • 一個月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$

  • 1到3個數字,後面跟著任意個 逗號+3個數字,逗號成為可選,而不是必須:^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$

  • 備註:這就是最終結果了,別忘了"+"可以用"*"替代如果你覺得空字串也可以接受的話(奇怪,為什麼?)最後,別忘了在用函式時去掉去掉那個反斜槓,一般的錯誤都在這裡

  • xml檔案:^([a-zA-Z]+-?)+[a-zA-Z0-9]+\.[x|X][m|M][l|L]$

  • 雙位元組字元:[^\x00-\xff] (包括漢字在內,可以用來計算字串的長度(一個雙位元組字元長度計2,ASCII字元計1))

  • 空白行的正規表示式:\n\s*\r (可以用來刪除空白行)

  • HTML標記的正規表示式:<(\S*?)[^>]>.?</\1>|<.*? />

  • 首尾空白字元的正規表示式:^\s*|\s*$或(^\s*)|(\s*$) (可以用來刪除行首行尾的空白字元(包括空格、製表符、換頁符等等),非常有用的表示式)

  • 騰訊QQ號:[1-9][0-9]{4,} (騰訊QQ號從10000開始)

  • 中國郵政編碼:[1-9]\d{5}(?!\d) (中國郵政編碼為6位數字)

  • IP地址:\d+.\d+.\d+.\d+ (提取IP地址時有用)

  • IP地址:((?:(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d?\d))

相關文章