JS 正則學習

要吃早餐發表於2018-07-13

正則一直都沒有好好學習過,每次做輸入框驗證,都到處找正則。今天就學習一下,以後不要在到處找了。
大部分是在網上找的資料,加上自己的理解。有不對的地方,請一定幫忙指出來。
參考資料:www.cnblogs.com/rubylouvre/… 和 MDN。

建立一個正規表示式

  let regex = /pattern/flags;
複製程式碼

其中的模式(pattern)部分就是各種各樣的正規表示式,可以包含字元類、限定類、分組、向前查詢一級反向引用。每個正規表示式都可帶有一個或多個標誌(flags),用來表明正規表示式的行為。正規表示式的匹配模式支援下列3個標誌。

正規表示式中的標誌

  • g : 表示全域性模式(global),模式將被應用於所有字串,而不是在發現第一個匹配項時立即停止。
  • i : 表示不區分大小寫模式,在確定匹配項時,會忽略大小寫。
  • m : 表示多行模式,在到達一行文字末尾時,繼續查詢下一行。

一個正規表示式就是一個模式與以上三個標誌的組合體。

正規表示式的模式。

  • 簡單模式
    簡單模式就是要查詢的字元直接匹配的。
    /abc/這個模式就匹配了一個字串中,abc同時出現並按照這個順序。
let regex = /abc/;
regex.test('ahkbcjjkabnc');  // false; 沒有匹配到
regex.test('abcaaalkjlkjlacjabc'); // true; 有匹配到
"abaaakjljabc".replace(regex, 'love'); // abaaakjljlove;  把匹配到的字串'abc'替換為 'love';
"aaabcaldjflj".search(regex) // 2  返回第一次匹配到的索引。沒有匹配到返回 -1;
複製程式碼
  • 使用特殊字元
    如果需要搜尋的條件比較複雜時,就要用到特殊字元。\

字元類

  1. 簡單類。
    原則上正則的一個字元對應一個字元,可以用[]把它們括起來,讓[]這個整體對應一個字元。
let reg = /[abc]/;
reg.test('a'); // true;
reg.test('c'); // true;
reg.test('ab'); // true;
reg.test('ac'); // true;
reg.test('ag'); // true;
reg.test('e'); // false;
複製程式碼
  1. 負向類
    []裡,前面加個 ^元字元進行取反,表示匹配不能為[]裡的字元。
let reg = /[^abc]/;
reg.test('a'); // false;
reg.test('ab'); // false;
reg.test('ag'); // true;   只要有一個字元不在 [] 裡就返回 true;
複製程式碼
  1. 範圍類
    []裡,有時匹配的東西過多,而且型別都一樣,就可以使用-符號,表示一個範圍。
let reg1 = /[a-d]/;
reg1.test('c'); // true;
reg1.test('e'); // false;
reg1.test('A'); // false;

let reg2 = /[A-Z]/;
reg2.test('a');     // false;
reg2.test('FGH');   // true;

let reg3 = /[1-8]/;
reg3.test(0);       // false;
reg3.test(456);     // true;
reg3.test(456.7);   // true;

let reg4 = /[^4-8]/;
reg4.test(3); // true;
reg4.test(6); // false;
複製程式碼
  1. 預定義類\
字元 等同於 描述
. [^\n\r] 除了換行和回車之外的任意字元
\d [0-9] 數字字元
\D [^0-9] 非數字字元
\s [ \t\n\xOB\f\r] 空白字元(注意是' ', 而不是 '')
\S [^ \t\n\xOB\f\r] 非空白字元
\w [a-zA-Z_0-9] 單詞字元
\W [^a-zA-Z_0-9] 非單詞字元
console.log(/\d/.test("3"))  // true;
console.log(/\d/.test("a"))  // false;
console.log(/\D/.test("a"))  // true;
console.log(/\D/.test("2"))  // false;
console.log(/\s/.test(" "))  // true;
console.log(/\s/.test(""))   // false;
console.log(/\s/.test("a"))  // false;
console.log(/\S/.test(" "))  // false;
console.log(/\S/.test(""))   // false;
console.log(/\S/.test("a"))  // true;
console.log(/\w/.test("d"))  // true;
console.log(/\w/.test("9"))   // true;
console.log(/\w/.test("!"))  // false;
console.log(/\W/.test("!"))  // true;
console.log(/\W/.test("@"))  // true;
console.log(/\W/.test("a"))  // false;
複製程式碼

量詞

由於元字元、特殊字元、或者字元類組合都是一對一進行匹配。有的時候需要匹配多次。這個時候就要用到量詞了。

程式碼 型別 描述
? 軟性量詞 出現 0 次或 1 次
* 軟性量詞 出現 0 次或多次(任意次)
+ 軟性量詞 出現一次或多次(至少一次)
{n} 硬性量詞 對應 n 次
{n, m} 軟性量詞 至少 n 次但不超過m 次
{n,} 軟性量詞 至少出現 n 次
``` javascript
console.log(/啊?/.test(''));        // true;
console.log(/啊?/.test('啊'));      // true;
'啊啊'.replace(/啊?/, '哈');        // 哈啊; // 只會匹配第一個滿足條件的字元。

console.log(/啊*/.test('啊'));      // true;
console.log(/啊*/.test('就瞭解瞭解'));      // true;
'啊啊'.replace(/啊*/, '哈');       // 哈  匹配到所有的 啊(全部),然後替換為 哈(一個)。

console.log(/啊+/.test('拉進來看見了就'))   // false;
console.log(/啊+/.test('啊哈哈哈路徑欄'))   // true;
'啊哈哈哈啊啊,啊哦哦'.replace(/啊+/, '不')  // "不哈哈哈啊啊,啊哦哦" 匹配到第一個 啊 ,替換為 不。

console.log(/啊{3}/.test('拉進來看見了就'))   // false;
console.log(/啊{3}/.test('啊啊哦哦哦哦哦哦')) // false;
console.log(/啊{3}/.test('啊啊哦哦哦哦哦哦啊')) // false;
console.log(/啊{3}/.test('啊啊哦哦哦哦哦哦啊啊啊'))  // true; 必須是連續的。
'哦哦啊啊啊哈哈哈'.replace(/啊{3}/, '哦');  // "哦哦哦哈哈哈"  匹配到 '啊啊啊', 然後替換為 '哦';
'哦哦啊啊啊哈哈哈'.replace(/啊/g, '哦');    // "哦哦哦哦哦哈哈哈"  每一個'啊' 都替換為 '哦';

console.log(/啊{2,5}/.test('啊哈哈哈哈哈哈'))  // false;
console.log(/啊{2,5}/.test('啊哈哈哈哈哈哈啊')) // false;
console.log(/啊{2,5}/.test('啊啊哈哈哈哈哈哈啊')) // true;
console.log(/啊{2,5}/.test('啊啊啊啊啊啊啊哈哈哈哈哈哈啊')) // true; 雖然超過了 5 個,但是還是返回 true; 這個時候匹配到的是前面 5 個 '啊'。
'啊啊啊啊啊啊啊哈哈哈哈哈哈啊'.replace(/啊{2,5}/, '哈'); // "哈啊啊哈哈哈哈哈哈啊" 匹配了5個'啊',替換為'哈';

console.log(/啊{3,}/.test('啊哈哈哈哈哈哈'))  // false;
console.log(/啊{3,}/.test('啊哈哈哈哈哈哈啊啊啊'))  // true;
'啊啊啊啊啊啊啊哈哈哈哈哈哈啊'.replace(/啊{3,}/, '哈');  // "哈哈哈哈哈哈哈啊"

/[\u4e00-\u9fa5]/用於匹配單個漢字。
console.log(/[\u4e00-\u9fa5]/.test('a')); //  false;
console.log(/[\u4e00-\u9fa5]/.test('啊a')); // true;
console.log(/[\u4e00-\u9fa5]/.test('34')); //  false;
```
複製程式碼

量詞分為 貪婪量詞與惰性量詞。

  • 貪婪量詞
    先看整個字串是不是一個匹配。如果沒有發現匹配,它去掉最後字串中的最後一個字元,並再次嘗試。如果還是沒有發現匹配,那麼 再次去掉最後一個字串,這個過程會一直重複直到發現一個匹配或者字串不剩任何字元。簡單量詞都是貪婪量詞。
  • 惰性量詞 先看字串中的第一個字母是不是一個匹配,如果單獨著一個字元還不夠,就讀入下一個字元,組成兩個字元的字串。如果還沒有發現匹配,惰性量詞繼續從字串中新增字元直到發現一個匹配或者整個字串都檢查過也沒有匹配。惰性量詞和貪婪量詞的工作方式恰好相反。

分組

上面介紹的都是單字元匹配,量詞雖然可以幫我們處理一排緊密相連的同型別字元,但這遠遠不夠。下面介紹一下小括號。 小括號允許重複多個字元,中括號表示範圍內選擇,大括號表示重複次數。

字元: (x)

let reg = /(sky)+/;
reg.test('lkjljskjjiuy');  // false
reg.test('skyjkjlsky');    // true;
複製程式碼

反向引用

正規表示式捕獲組匹配的字串,可以用編號進行標識,並通過 "\編號"進行引用。
有 九個 用來儲存捕獲組的建構函式屬性。訪問這些屬性的語法是: RegExp.$1RegExp.$2.....RegExp.$9,分別用來儲存第一、第二......第九個匹配的捕獲組。在呼叫test()exec()方法時,這些屬性會自動填充。

let text = "this has been a short summer";
let reg = /(..)or(.)/g;

if (reg.test(text)) {
    console.log(RegExp.$1);  //  sh
    console.log(RegExp.$2);  //  t 
}
複製程式碼

上面建立了一個包含兩個捕獲組的模式,然後用該模式測試了一個字串,儘管test()方法只返回了true,但RegExp建構函式的屬性$1$2也會被匹配相應捕獲組的字串自動填充。

字元:\n
n是一個正整數,一個反向引用,指向正規表示式中第n個括號(從左往右)中匹配的字串。

let reg = /abc(de)(fg)\1/; 相當於: /abc(de)(fg)(de)/;
reg.test('abcdefg');   // false
reg.test('abcdefgde');   // true
複製程式碼

候選

在分組中插入|管道符,可以劃分多個候選項。

let reg = /(red|yellow|green)\?/;
reg.test('bloackred');  // false;
reg.test('bloackred?');  // true;
reg.test('yellow?');    // true;
reg.test('green?');     // true;
複製程式碼

非捕獲分組

並不是所有的分組都能建立反向引用(也就是建立捕獲組)。要建立一個非捕獲性分組,只要在分組的左括號的後面加一個問號?與冒號:。字元(?:x);

let text = "this has been a short summer";
let reg = /(?:..)or(?:.)/g;

if (reg.test(text)) {
    console.log(RegExp.$1);  //  ''; 非捕獲組。
}
複製程式碼

查詢

  • 正向肯定查詢
    用來檢查接下來出現的是不是某個特定的字符集。
    字元:x(?=y)
let reg = /我的天(?=空)/;
reg.test('這是我的天空');  // true
reg.test('哦!我的天啊');  // false;
'我的天下'.replace(reg, '啊啊');  // "我的天下"。 並沒有匹配到,所以就沒有替換。
'我的天空為何'.replace(reg, '阿');  // "阿空為何"
複製程式碼
  • 正向否定查詢
    用來檢查接下來不應該出現的字符集。
    字元:x(?!y)
let reg = /abc(?!de)/;
reg.test('abcdefg');  // false;
reg.test('abcd');  // true;
reg.test('abcabc');   // true;
複製程式碼

邊界

一個要與字元類合用的東西。

正則 名稱 描述
^ 開頭 注意不能緊跟在[中括號的後面。
$ 結尾
\b 單詞邊界 指[a-zA-Z_o-9]之外的字元。匹配一個零寬單詞邊界,如一個字母與一個空格之間。
\B 非單詞邊界

邊界詳解

  • 單詞邊界(\b)
    匹配一個零寬單詞邊界,如一個字母與一個空格之間。

    let reg1 = /\bde/;
    reg.test('abcde');  // false;
    reg.test('abc de');  // true;
    reg.test('abc&de');  // true;
    
    let reg2 = /fg\b/;
    reg2.test('abcdefg');  // true;
    reg2.test('abcdefghh');  // false;
    reg2.test('abcdefg#');  // true;
    複製程式碼
  • 非單詞邊界(\B)
    匹配一個零寬非單詞邊界,如兩個字母之間,或兩個空格之間。

    let reg1 = /\Bde/;
    reg.test('abcdefg');   // true;
    reg.test('abc defg');  // false;
    reg.test('abc&defg'); // false;
    reg.test('abc de fg');  // false;
    
    let reg2 = /de\B/;
    reg2.test('abcdefg');  // true;
    reg2.test('abcde');    // false;
    reg2.test('abcde&fg');  // false;
    複製程式碼

    一些常用的正則總結

    • 正整數

    驗證規則:
    1、允許0
    2、不允許01、02...

    reg = /^[1-9]\d*|0$/;
    console.log('02');   // false;
    console.log(02);     // true;  因為程式在處理的時候,把02作為2進行處理,所以會返回true。需要先轉為字串。
    複製程式碼
    • 手機號碼

    驗證規則:
    1、11位數字
    2、以1開頭

    reg = /^1\d{10}$/;
    複製程式碼
    • 電話號碼

    驗證規則
    1、區號 + 號碼
    2、區號以 0 開頭,3位或4位
    3、號碼由7位或8位數字組成
    4、區號與號碼之間可以無連線符,也可以“-”連線

    reg =  /^0\d{2,3}-?\d{7,8}$/;
    複製程式碼

相關文章