寫網頁需要用 Regular Expression 在字串裡找特定關鍵字,發現 2022 年了,我還沒完全搞懂 RegExp.exec()String.match() / matchAll() 的用法及差異,趕緊做個練習壓壓驚。

用法說明都寫在註解,請直接看 Code !

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <script>

            // *** 練習一 完整用法,具名群組 ***
            console.log('%c練習一 完整用法,具名群組', 'color: yellow;');
            var sample = "我達達的馬蹄是美麗的錯誤 我不是歸人,是個過客……";
            // 找出 XX的XX 形容詞加名詞
            var regex = /(?<adj>\S\S的)\S\S/;
            // 或寫成 regex_g = new RegExp("(?<adj>\\S\\S的)\\S\\S", "g");
            var regex_g = /(?<adj>\S\S的)\S\S/g;

            function test(expression) {
                console.log('%c' + expression, 'color:cyan;');
                console.log(eval(expression));
            }

            // 測試 String.match
            test('sample.match(regex)');
            //['達達的馬蹄', '達達的', index: 1, input: '我達達的...略', groups: {adj: '達達的'}]
            // 未加上 g 修飾符時,String.match 執行結果與 RegExp.exec 相同,
            // 只回傳第一個符合的結果,沒找到符合的話回傳 null
            test('regex.exec(sample)');
            //['達達的馬蹄', '達達的', index: 1, input: '我達達的...略', groups: {adj: '達達的'}]
            // 當有 g 修飾符時,String.match 會回傳所有符合的結果,沒找到符合的話回傳 null
            test('sample.match(regex_g)');
            // ['達達的馬蹄', '美麗的錯誤']

            // 當有 g 修飾符時,RegExp.exec 會回傳第一筆,並更新 lastIndex,沒找到符合的話回傳 null
            test('regex_g.lastIndex'); // 原本是 0 ,因為沒有執行過 exec
            test('regex_g.exec(sample)'); 
            // ['達達的馬蹄', '達達的', index: 1, input: '我達達的...略', groups: {adj: '達達的'}]
            test('regex_g.lastIndex'); // 找到第一筆後變成 6
            // 再執行一次 exec,會從上次的 lastIndex 開始找
            test('regex_g.exec(sample)'); 
            // ['美麗的錯誤', '美麗的', index: 7, input: '我達達的...略', groups: {adj: '美麗的'}]
            test('regex_g.lastIndex'); // 找到第二筆後變成 12
            // 再執行一次 exec,會從上次的 lastIndex 開始找,找不到便回傳 null
            test('regex_g.exec(sample)');
            // null

            // String.matchAll 可傳回完整符合結果的 iterator,得到類似 RegExp.exec 的結果
            test('[...sample.matchAll(regex_g)]');
            // ['達達的馬蹄', '達達的', index: 1, input: '我達達的...略', groups: {adj: '達達的'}]
            // ['美麗的錯誤', '美麗的', index: 7, input: '我達達的...略', groups: {adj: '美麗的'}]
                       
            // *** 練習二 不具名群組 ***
            console.log('%c練習二 不具名群組', 'color: yellow;');
            var regex = /(\S\S的)\S\S/;
            // 或寫成 regex_g = new RegExp("(?<adj>\\S\\S的)\\S\\S", "g");
            var regex_g = /(\S\S的)\S\S/g;         
            
            // 測試 String.match
            test('sample.match(regex)');
            // ['的', index: 3, input: '我達達的...略', groups: undefined]
            test('sample.match(regex_g)');
            // ['的', '是', '的', '是', '是']
            
            // 測試 RegExp.exec
            test('regex.exec(sample)');
            // ['的', index: 3, input: '我達達的...略', groups: undefined]
            test('regex_g.exec(sample)');
            // ['的', index: 3, input: '我達達的...略', groups: undefined]
            
            // *** 練習三 不定義群組 ***
            console.log('%c練習三 不定義群組', 'color: yellow;');
            // 找出「的」或「是」
            var regex = /[是的]/; // 或寫成 /是|的/;
            var regex_g = /[是的]/g;

            // 測試 String.match
            test('sample.match(regex)');
            // ['的', index: 3, input: '我達達的...略', groups: undefined]
            test('sample.match(regex_g)');
            // ['的', '是', '的', '是', '是']
            
            // 測試 RegExp.exec
            test('regex.exec(sample)');
            // ['的', index: 3, input: '我達達的...略', groups: undefined]
            test('regex_g.exec(sample)');
            // ['的', index: 3, input: '我達達的...略', groups: undefined]
            
        </script>
    </body>
</html>

實測結果:

Examples of RegExp.exec() and String.match() usage.


Comments

Be the first to post a comment

Post a comment