(76)Wangdao.com第十四天_JavaScript 正則表達式對象 RegExp

RegExphtml

Regular Expression,正則表達式是一種表達    文本模式(字符串結構)  的式子。web

經常用來按照「給定模式」匹配文本。好比,正則表達式給出一個 Email 地址的模式,而後用它來肯定一個字符串是否爲 Email 地址。正則表達式

JavaScript 的正則表達式體系是參照 Perl 5 創建的數組

  • 新建正則表達式的兩種方式
    • 使用字面量,以斜槓表示開始和結束
      • 在引擎編譯代碼時,就會新建正則表達式。
      • 因此效率相對較高,並且,前者比較便利和直觀,因此實際應用中,基本上都採用字面量定義正則表達式
      • var regex = /xyz/;

        var regex = /xyz/ig; // i 和 g 爲兩個修飾符

         

    • 使用 new RegExp() 構造函數
      • 在運行時新建正則表達式
      • var regex = new RegExp('xyz');

        var regex = new RegExp('xyz', 'i'); // i 和 g 爲兩個修飾符

         

  • 正則對象的實例屬性
    • 與修飾符相關的屬性,返回一個布爾值,表示對應的修飾符是否設置
      • RegExp.prototype.ignoreCase    返回一個布爾值,表示是否設置了 i 修飾符
      • RegExp.prototype.global    返回一個布爾值,表示是否設置了 g 修飾符
      • RegExp.prototype.multiline    返回一個布爾值,表示是否設置了 m 修飾符
    • 與修飾符無關的屬性,主要是下面兩個
      • RegExp.prototype.lastIndex  返回一個整數,表示下一次開始搜索的位置。該屬性可讀寫,可是隻在進行連續搜索時有意義
      • RegExp.prototype.source  返回正則表達式的字符串形式(不包括反斜槓),該屬性只讀

 

  • 匹配規則
  • 字面量字符
    • 若是在正則表達式之中,某個字符只表示它字面的含義(好比/a/匹配a/b/匹配b),那麼它們就叫作「字面量字符」(literal characters)。
  • 元字符
    • 除了字面量字符之外,還有一部分字符有特殊含義,不表明字面的意思。它們叫作「元字符」(metacharacters)
      • 點字符(.)
        • 點字符(.匹配除回車(\r換行(\n)行分隔符(\u2028段分隔符(\u2029之外的全部字符
        • 對於碼點大於0xFFFF字符,點字符不能正確匹配,會認爲這是兩個字符
      • 位置字符        用來提示字符所處的位置,主要有兩個字符
        • ^ 表示字符串的開始位置網絡

        • $ 表示字符串的結束位置app

      • 選擇符(|
        • 表示「或關係」(OR)
        • /11|22/.test('911');    // true    指定必須匹配到 或 1122
        • 選擇符會包括它先後的多個字符,好比/ab|cd/指的是匹配ab或者cd,而不是指匹配b或者c
          • 若是想修改這個行爲,可使用圓括號
            /a( |\t)b/.test('a\tb');    // true

             

      • 還包括\\*+?()[]{}等等,將在下文解釋

 

  • 轉義符
    • 那些有特殊含義的元字符,若是要匹配它們自己,就須要在它們前面要加上反斜槓。
    • 好比要匹配+,就要寫成\+
    • 須要反斜槓轉義的,一共有12個字符:{    \
    • 注意 若是使用RegExp方法生成正則對象,轉義須要使用兩個斜槓,由於字符串內部會先轉義一次
      • (new RegExp('1\+1')).test('1+1');    // false
        
        (new RegExp('1\\+1')).test('1+1');    // true
        // 做爲構造函數,參數是一個字符串。可是,在字符串內部,反斜槓也是轉義字符,因此它會先被反斜槓轉義一次,而後再被正則表達式轉義一次,所以須要兩個反斜槓轉義

 

  • 特殊字符

對一些不能打印的特殊字符,提供了表達方法函數

\cX        用來匹配控制字符,表示Ctrl-[X],其中的X是A-Z之中任一個英文字母,
ui

[\b]        匹配退格鍵(U+0008),不要與\b混淆google

\n          匹配換行鍵編碼

\r           匹配回車鍵

\t           匹配製表符 tab(U+0009)

\v          匹配垂直製表符(U+000B)

\f           匹配換頁符(U+000C)

\0          匹配null字符(U+0000)

\xhh      匹配一個以兩位十六進制數(\x00-\xFF)表示的字符

\uhhhh  匹配一個以四位十六進制數(\u0000-\uFFFF)表示的 Unicode 字符

 

  • 符類 [ ]

[ ] 表示有一系列字符可供選擇,只要匹配其中一個就能夠了

全部可供選擇的字符都放在方括號內,

好比[xyz] 表示xyz之中任選一個匹配

    • 有兩個字符在字符類中有特殊含義
      • 脫字符 ^
        • 若是方括號內的第一個字符是[^],則表示除了字符類之中的字符,其餘字符均可以匹配
        • 好比,[^xyz] 表示除了xyz以外均可以匹配
        • 若是方括號內沒有其餘字符,即只有[^],就表示匹配一切字符,其中包括換行符
          • 相比之下,點號做爲元字符(.)是不包括換行符的
            var s = 'Please yes\nmake my day!';
            
            s.match(/yes.*day/);    // null    含有一個換行符,點號不包括換行符,因此第一個正則表達式匹配失敗
            s.match(/yes[^]*day/);    // [ 'yes\nmake my day']    包含一切字符,因此匹配成功s[^]

             

      • 連字符 -
        • 用來提供簡寫形式,表示字符的連續範圍,
        • 當連字號(dash)不出如今方括號之中,就不具有簡寫的做用,只表明字面的含義
        • 好比,[abc]能夠寫成[a-c][0123456789]能夠寫成[0-9],同理[A-Z]表示26個大寫字母
        • 連字符還能夠用來指定 Unicode 字符的範圍
        • 不要過度使用連字符,設定一個很大的範圍,不然極可能選中意料以外的字符。最典型的例子就是[A-z],表面上它是選中從大寫的A到小寫的z之間52個字母,可是因爲在 ASCII 編碼之中,大寫字母與小寫字母之間還有其餘字符,結果就會出現意料以外的結果
          • var str = "\u0130\u0131\u0132";
            /[\u0128-\uFFFF]/.test(str);    // true
            // \u0128-\uFFFF 表示匹配碼點在0128到FFFF之間的全部字符

             

 

  • 預約義模式

指的是某些常見模式的簡寫方式

\d 匹配0-9之間的任一數字,至關於 [0-9]

\D 匹配全部0-9之外的字符,至關於 [^0-9]

 

\w 匹配任意的字母、數字和下劃線,至關於 [A-Za-z0-9_]

\W 除全部字母、數字和下劃線之外的字符,至關於 [^A-Za-z0-9_]

 

\s 匹配空格(包括換行符、製表符、空格符等),相等於[ \t\r\n\v\f]

  • 一般,正則表達式遇到 換行符 \n 就會中止匹配,這時使用 \s 字符類,就能包括換行符
    var html = "<b>Hello</b>\n<i>world!</i>";
    
    /[\S\s]*/.exec(html)[0];    // "<b>Hello</b>\n<i>world!</i>"
    
    // [\S\s]指代一切字符

     

\S 匹配非空格的字符,至關於[^ \t\r\n\v\f]

 

\b 匹配詞的邊界

\B 匹配非詞邊界,即在詞的內部

  • // \s 的例子
    /\s\w*/.exec('hello world');    // [" world"]
    
    // \b 的例子
    /\bworld/.test('hello world');    // true
    /\bworld/.test('hello-world');    // true
    /\bworld/.test('helloworld');    // false
    
    // \B 的例子
    /\Bworld/.test('hello-world');    // false
    /\Bworld/.test('helloworld');    // true

     

  • 重複類

模式的精確匹配次數,使用大括號 { } 表示重複類

{n}表示剛好重複n次,

{n,}表示至少重複n次,

{n,m}表示重複很多於n次,很少於m

  • /lo{2}k/.test('look');    // true    指定o連續出現2次
    /lo{2,5}k/.test('looook');    // true    指定o連續出現2次到5次之間

     

  • 量詞符

用來設定某個模式出現的次數

? 問號表示某個模式出現0次或1次,等同於{0, 1}

* 星號表示某個模式出現0次或屢次,等同於{0,}

+ 加號表示某個模式出現1次或屢次,等同於{1,}

  • // t 出現0次或1次
    /t?est/.test('test');    // true
    /t?est/.test('est');    // true
    
    // t 出現1次或屢次
    /t+est/.test('test');    // true
    /t+est/.test('ttest');    // true
    /t+est/.test('est');    // false
    
    // t 出現0次或屢次
    /t*est/.test('test');    // true
    /t*est/.test('ttest');    // true
    /t*est/.test('tttest');    // true
    /t*est/.test('est');    // true

 

  • 貪婪模式

默認狀況下都是最大可能匹配,即匹配直到下一個字符不知足匹配規則爲止。這被稱爲貪婪模式

    • var s = 'aaa';
      s.match(/a+/);    // ["aaa"]
      // 模式是/a+/,表示匹配1個a或多個a,那麼到底會匹配幾個a呢?
      // 由於默認是貪婪模式,會一直匹配到字符a不出現爲止,因此匹配結果是3個a

      var s = 'aaa'; s.match(/a+?/) // ["a"] 模式結尾添加了一個問號/a+?/,這時就改成非貪婪模式,一旦條件知足,就再也不往下匹配


  • 若是想將貪婪模式改成非貪婪模式,能夠在量詞符後面加一個問號
    • +?    表示某個模式出現1次或屢次,匹配時採用非貪婪模式
    • *?    表示某個模式出現0次或屢次,匹配時採用非貪婪模式
    • ??    表示某個模式出現0次或1次,匹配時採用非貪婪模式

 

  • 修飾符

表示模式的附加規則,放在正則模式的最尾部

能夠單個使用,也能夠多個一塊兒使用

  • g 修飾符
    • 表示全局匹配(global),加上它之後,正則對象將匹配所有符合條件的結果,主要用於搜索和替換
      • // 正則模式含有g修飾符,每次都是從上一次匹配成功處,開始向後匹配。
        
        var regex = /b/g;
        var str = 'abba';
        
        regex.test(str); // true
        regex.test(str); // true
        regex.test(str); // false
        
        // 由於字符串abba只有兩個b,因此前兩次匹配結果爲true,第三次匹配結果爲false

         

  • i 修飾符
    • 加上i修飾符之後表示忽略大小寫(ignorecase)
      • /abc/.test('ABC');    // false
        /abc/i.test('ABC');    // true
        
        // 加了i修飾符之後,不考慮大小寫,因此模式abc匹配字符串ABC

         

  • m 修飾符
    • 表示多行模式(multiline),會修改 和 的行爲
    • 加上m修飾符之後,和 還會匹配行首和行尾,即 和 會識別換行符(\n
      • /world$/.test('hello world\n');    // false
        /world$/m.test('hello world\n');    // true
        // 字符串結尾處有一個換行符。若是不加m修飾符,匹配不成功,由於字符串的結尾不是world;加上之後,$能夠匹配行尾

        /^b/m.test('a\nb'); // true
        // 若是不加m修飾符,就至關於b只能處在字符串的開始處。加上b修飾符之後,換行符\n也會被認爲是一行的開始
        mbb\n

 

  • 組匹配 ( )

括號表示分組匹配,括號中的模式能夠用來匹配分組的內容

  • /fred+/.test('fredd');    // true    結果+只表示重複字母d
    /(fred)+/.test('fredfred');    // true    有括號,結果+就表示匹配fred這個詞
  • 使用組匹配時,不宜同時使用g修飾符,不然match方法不會捕獲分組的內容 
    • var m = 'abcabc'.match(/(.)b(.)/g);
      m    // ['abc', 'abc']
      // 帶 g 修飾符的正則表達式,結果match方法只捕獲了匹配整個表達式的部分
      
      
      // 這時必須使用正則表達式的exec方法,配合循環,才能讀到每一輪匹配的組捕獲
      var str = 'abcabc';
      var reg = /(.)b(.)/g;
      while (true) {
          var result = reg.exec(str);
          if (!result){
              break;
          }
          console.log(result);
      }
      // ["abc", "a", "c"]
      // ["abc", "a", "c"]

       

  • 內部,還能夠用  "\數字" 引用括號匹配的內容,數字是從1開始的天然數,表示對應順序的括號匹配到的內容
    • /(.)b(.)\1b\2/.test("abcabc");    // true

       

  • 括號還能夠嵌套
    • /y((..)\2)\1/.test('yabababab');    // true    指向外層括號,指向內層括號\1\2

       

  • 組匹配很是有用
    • var tagName = /<([^>]+)>[^<]*<\/\1>/;    // 圓括號 匹配 尖括號之中的標籤,就表示 對應的閉合標籤
      
      tagName.exec("<b>bold</b>")[1];    // 'b'\1

       

  • 下面是一個匹配網頁標籤的例子,捕獲帶有屬性的標籤
    • var html = '<b class="hello">Hello</b><i>world</i>';
      var tag = /<(\w+)([^>]*)>(.*?)<\/\1>/g;
      
      var match = tag.exec(html);
      
      match[1]    // "b"
      match[2]    // " class="hello""
      match[3]    // "Hello"
      
      match = tag.exec(html);
      
      match[1]    // "i"
      match[2]    // ""
      match[3]    // "world"

 

  • 非捕獲組   (?:x)

表示不返回該組匹配的內容,即這個括號中匹配的內容不計入結果

  • 假定須要匹配foo或者foofoo,正則表達式就應該寫成/(foo){1, 2}/,可是這樣會佔用一個組匹配。這時,就可使用非捕獲組,將正則表達式改成/(?:foo){1, 2}/,它的做用與前一個正則是同樣的,可是不會單獨輸出括號內部的內容
    • var m = 'abc'.match(/(?:.)b(.)/);
      m    // ["abc", "c"]    // 第一個括號是非捕獲組,因此最後返回的結果中沒有第一個括號,只有第二個括號匹配的內容

       

  • 用來分解網址的正則表達式
    • // 正常匹配    第一個括號返回網絡協議
      var url = /(http|ftp):\/\/([^/\r\n]+)(\/[^\r\n]*)?/;
      url.exec('http://google.com/');
      // ["http://google.com/", "http", "google.com", "/"]
      
      // 非捕獲組匹配 返回結果中不包括網絡協議 var url = /(?:http|ftp):\/\/([^/\r\n]+)(\/[^\r\n]*)?/; url.exec('http://google.com/'); // ["http://google.com/", "google.com", "/"]

 

  • 先行斷言 x(?=y)

只有在 y前面才匹配,y 不會被計入返回結果。即括號裏的部分是不會返回的

好比,要匹配後面跟着百分號的數字,能夠寫成/\d+(?=%)/

    • var m = 'abc'.match(/b(?=c)/);
      m     // ["b"]    使用了先行斷言,b在c前面因此被匹配,可是括號對應的c不會被返回

 

  • 先行否認斷言 x(?!y)

只有不在y前面才匹配,y不會被計入返回結果。即括號裏的部分是不會返回的

好比,要匹配後面跟的不是百分號的數字,就要寫成/\d+(?!%)/

    • 指定,只有不在小數點前面的數字纔會被匹配
      • /\d+(?!\.)/.exec('3.14')    // ["14"]

         

    • b不在c前面因此被匹配,並且括號對應的d不會被返回
      • var m = 'abd'.match(/b(?!c)/);    m // ['b']

 

  • 正則對象的實例方法
    • RegExp.prototype.test()    
      • 表示當前模式是否能匹配參數字符串返回一個布爾值
      • /cat/.test('cats and dogs');    // true    驗證參數字符串之中是否包含 cat

         

      • 若是正則模式是一個空字符串,則匹配全部字符串
      • g 修飾符,表示是全局搜索,會有多個結果。
      • 帶有g修飾符時,能夠經過正則對象的 lastIndex 屬性指定開始搜索的位置
      • 若是正則表達式帶有 g 修飾符,則每一次 test 方法都從上一次結束的位置開始向後匹配
      • var r = /x/g;
        var s = '_x_x';
        
        r.lastIndex // 0
        r.test(s) // true
        
        r.lastIndex // 2
        r.test(s) // true
        
        r.lastIndex // 4
        r.test(s) // false

         

      • lastIndex屬性只對同一個正則表達式有效,因此下面這樣寫是錯誤的
        • var count = 0;
          while (/a/g.test('babaa')){
              count++;
          }    // 無限循環,由於while循環的每次匹配條件都是一個新的正則表達式,致使lastIndex屬性老是等於0

           

    • RegExp.prototype.exec()
      • 用來返回匹配結果。
      • 若是發現匹配,就返回一個數組。成員是匹配成功的子字符串。不然返回null
        • var s = '_x_x';
          var r1 = /x/;
          var r2 = /y/;
          
          r1.exec(s);    // ["x"]
          r2.exec(s);    // null

           

      • 若是正則表示式包含圓括號(即含有「組匹配」),則返回的數組會包括多個成員。
        • 第一個成員是整個匹配成功的結果,後面的成員就是圓括號對應的匹配成功的組。
        • 也就是說,
          • 第二個成員對應第一個括號,
          • 第三個成員對應第二個括號,以此類推。
        • 整個數組的length屬性等於組匹配的數量再加1
        • var s = '_x_x';
          var r = /_(x)/;
          
          r.exec(s);    // ["_x", "x"]    返回一個數組。第一個成員是整個匹配的結果,第二個成員是圓括號匹配的結果。

          exec方法的返回數組還包含如下兩個屬性:

          • input    整個原字符串
          • index    整個模式匹配成功的開始位置(從0開始計數)
            var r = /a(b+)a/;
            var arr = r.exec('_abbba_aba_');
            
            arr    // ["abbba", "bbb"]
            arr.index    // 1    屬性等於1,是由於從原字符串的第二個位置開始匹配成功
            arr.input    // "_abbba_aba_"index

             

      • 若是正則表達式加上g修飾符,則可使用屢次exec方法,下一次搜索的位置從上一次匹配成功結束的位置開始
        • var reg = /a/g;
          var str = 'abc_abc_abc'
          
          var r1 = reg.exec(str);
          r1    // ["a"]
          r1.index    // 0
          reg.lastIndex    // 1
          
          var r2 = reg.exec(str);
          r2    // ["a"]
          r2.index    // 4
          reg.lastIndex    // 5
          
          var r3 = reg.exec(str);
          r3    // ["a"]
          r3.index    // 8
          reg.lastIndex    // 9
          
          var r4 = reg.exec(str);
          r4    // null
          reg.lastIndex    // 0
          // 前三次都是從上一次匹配結束的位置向後匹配。
          // 當第三次匹配結束之後,整個字符串已經到達尾部,匹配結果返回,正則實例對象的屬性也重置爲,意味着第四次匹配將從頭開始
          nulllastIndex0

          利用g修飾符容許屢次匹配的特色,能夠用一個循環完成所有匹配

          • var reg = /a/g;
            var str = 'abc_abc_abc'
            
            while(true) {
                var match = reg.exec(str);    // 匹配到末尾,匹配失敗,返回 null
                if (!match) break;
                console.log('#' + match.index + ':' + match[0]);
            }
            // #0:a
            // #4:a
            // #8:a

             

  • 字符串的實例方法

在字符串中有 4 中與正則表達式相關的實例方法。

    • String.prototype.match()
      • 對字符串進行正則匹配,返回一個數組,成員是全部匹配的子字符串
      • 與正則對象的exec方法很是相似:匹配成功返回一個數組,匹配失敗返回 null
      • 若是正則表達式帶有g修飾符,會一次性返回全部匹配成功的結果
      • 匹配老是從字符串的第一個字符開始,設置正則表達式的lastIndex屬性,對match方法無效
        • var s = '_x_x';
          var r1 = /x/;
          var r2 = /y/;
          
          s.match(r1);    // ["x"]
          s.match(r2);    // null
          
          //////////////////////////////////////
          
          var s = 'abba';
          var r = /a/g;
          
          s.match(r);    // ["a", "a"]    一次性返回搜索到的結果
          r.exec(s);    // ["a"]    一次返回只有一個結果的一個數組    lastIndex 後移

           

    • String.prototype.search()
      • 返回第一個知足條件的匹配結果在整個字符串中的位置。若是沒有任何匹配,則返回-1
        • '_x_x'.search(/x/);    // 1    第一個匹配結果出如今字符串的1號位置

           

    • String.prototype.replace()
      • 按照給定的正則表達式進行替換,返回替換後的字符串
      • 能夠替換匹配的值。
      • 它接受兩個參數
          • str.replace(search, replacement);
        • 第一個是正則表達式,表示搜索模式,
        • 第二個是替換的內容
          • 'aaa'.replace('a', 'b');     // "baa"
            'aaa'.replace(/a/, 'b');     // "baa"
            'aaa'.replace(/a/g, 'b');    // "bbb"    使用了修飾符,致使全部的都被替換掉了gb

             

      • 正則表達式若是不加g修飾符,就替換第一個匹配成功的值,不然替換全部匹配成功的值
      • 應用 :  就是消除字符串首尾兩端的空格
        • var str = '  #id div.class  ';
          
          str.replace(/^\s+|\s+$/g, '');    // "#id div.class"

           

      • replace方法的第二個參數可使用美圓符號$,用來指代所替換的內容
        • $&    匹配的子字符串。
          $`    匹配結果前面的文本。
          $'    匹配結果後面的文本。
          $n    匹配成功的第n組內容,n是從1開始的天然數。
          $$    指代美圓符號$。
          • 'hello world'.replace(/(\w+)\s(\w+)/, '$2 $1');
            // "world hello"
            
            'abc'.replace('b', '[$`-$&-$\']');
            // "a[a-b-c]c"

             

      • 第二個參數還能夠是一個函數,將每個匹配內容替換爲函數返回值
        • '3 and 5'.replace(/[0-9]+/g, function (match) {
              return 2 * match;
          })
          // "6 and 10"
          
          var a = 'The quick brown fox jumped over the lazy dog.';
          var pattern = /quick|brown|lazy/ig;
          
          a.replace(pattern, function replacer(match) {
              return match.toUpperCase();
          });
          // The QUICK BROWN fox jumped over the LAZY dog.

           

      • 做爲replace方法第二個參數的替換函數,能夠接受多個參數。
        • 其中,第一個參數是捕捉到的內容,
        • 第二個參數是捕捉到的組匹配(有多少個組匹配,就有多少個對應的參數)。
        • 此外,最後還能夠添加兩個參數,倒數第二個參數是捕捉到的內容在整個字符串中的位置(好比從第五個位置開始),
          • 最後一個參數是原字符串。下面是一個網頁模板替換的例子
            var prices = {
                'p1': '$1.99',
                'p2': '$9.99',
                'p3': '$5.00'
            };
            
            var template = '<span id="p1"></span>'
              + '<span id="p2"></span>'
              + '<span id="p3"></span>';
            
            template.replace(
                /(<span id=")(.*?)(">)(<\/span>)/g,
                function(match, $1, $2, $3, $4){    // 有四個括號,因此會產生四個組匹配,在匹配函數中用到表示。匹配函數的做用是將價格插入模板中
                    return $1 + $2 + $3 + prices[$2] + $4;
                }
            );
            // "<span id="p1">$1.99</span><span id="p2">$9.99</span><span id="p3">$5.00</span>"$1$4

             

    • String.prototype.split()
      • 按照給定規則進行字符串分割,返回一個數組,包含分割後的各個成員
        • str.split(separator,  [limit]);
      • 第一個參數是正則表達式,表示分隔規則
      • 第二個參數是返回數組的最大成員數
          • // 非正則分隔
            'a,  b,c, d'.split(',');    // [ 'a', '  b', 'c', ' d' ]
            
            // 正則分隔,去除多餘的空格
            'a,  b,c, d'.split(/, */);    // [ 'a', 'b', 'c', 'd' ]
            
            // 指定返回數組的最大成員
            'a,  b,c, d'.split(/, */, 2);    [ 'a', 'b' ]

             

          • // 例一
            'aaa*a*'.split(/a*/);    // [ '', '*', '*' ]
            // 分割規則是0次或屢次的a,因爲正則默認是貪婪匹配,因此例一的第一個分隔符是aaa,第二個分割符是a,將字符串分紅三個部分,包含開始處的空字符串
            
            
            // 例二
            'aaa**a*'.split(/a*/);    // ["", "*", "*", "*"]
            // 第一個分隔符是aaa,第二個分隔符是0個a(即空字符),第三個分隔符是a,因此將字符串分紅四個部分

             

      • 若是正則表達式帶有括號,則括號匹配的部分也會做爲數組成員返回
        • 'aaa*a*'.split(/(a*)/);    // [ '', 'aaa', '*', 'a', '*' ]
          // 正則表達式使用了括號,第一個組匹配是aaa,第二個組匹配是a,它們都做爲數組成員返回

           

好比,[abc]能夠寫成[a-c][0123456789]能夠寫成[0-9],同理[A-Z]表示26個大寫字母

相關文章
相關標籤/搜索