js 정규 표현 식 문법 강조

며칠 동안 정칙 을 배 웠 는데 하마터면 정리 하고 성 과 를 써 야 할 뻔 했다.그 전에 문법 이 하 이 라이트 와 일치 하 는 것 을 쓰 려 고 했 지만 수준 이 부족 해서 예 를 들 어도 이해 하지 못 했다.
그렇다면 두 명의 대신 차 탄산 코발트 와 Barret Lee 의 문법 적 하 이 라이트 실현 을 분석 해 보 자.
Barret Lee 의 이'몇 가지 작은 예 를 들 어 정규 표현 식 하 이 라이트 하 이 라 이 트 를 실현 하 는 방법 을 알려 드 립 니 다.'부터 말씀 드 리 겠 습 니 다.
이전에 보 았 을 때 신기 하 다 고 만 느 꼈 다.특히 아래 의 그 한 걸음 한 걸음 일치 하 는 예 는 더욱 패기 가 새 는 것 을 측정 했다.그러나 작 가 는 헤 어 지 는 것 은 단지 시범 을 보 여 주 는 것 일 뿐 이 단계 가 무엇 과 일치 하 는 지 직관 적 으로 볼 수 있다 고 말 했다.그렇지 않 으 면 한 걸음 에 일치 하 는 것 이 완성 되 고 무슨 일이 일 어 났 는 지 모 르 고 처리 할 수 있다 고 말 했다.그의 정규 를 살 펴 보 자

(/^\s+|\s+$/) //
(/(["'])(?:\\.|[^\\
])*?\1/) //
(/\/(?!\*|span).+\/(?!span)[gim]*/) // span ,
(/(\/\/.*|\/\*[\S\s]+?\*\/)/) //
(/(\*\s*)(@\w+)(?=\s*)/) //
(/\b(break|continue|do|for|in|function|if|else|return|switch|throw|try|catch|finally|var|while|with|case|new|typeof|instance|delete|void|Object|Array|String|Number|Boolean|Function|RegExp|Date|Math|window|document|navigator|location|true|false|null|undefined|NaN)\b/) //
콧수염 형 은 바퀴 를 다시 만 들 고 싶 지 않 은 지 이런 바퀴 를 어떻게 만 드 는 지 알 고 싶 었 을 뿐 이 었 다.그래서 그 는 이 물건 을 찍 으 면 바로 멈 추고 깊이 있 게 처리 하지 않 아 거 칠 게 만 들 었 다.물론 나 도 그 가 뭐라고 말 하 는 것 은 아니다.단지 간단하게 평론 할 뿐이다.왜냐하면 우수한 문법 하 이 라이트 플러그 인 은 스스로 반복 해서 만 들 필요 가 없고 원 리 를 배우 면 된다.
다음 탄산 코발트 라 는'정규 표현 식 의 JavaScript 코드 하 이 라 이 트 를 어떻게 실현 합 니까?'을 분석 해 보 겠 습 니 다.사실 이 편 은 이미 매우 상세 하 게 분석 되 었 습 니 다.저 는 간단하게 보충 설명 할 수 밖 에 없습니다.차 탄산 코 발 트 는 항상 생각 이 엄밀 합 니 다.이 글 을 읽 기 전에 저 는 한 시간 넘 게 봤 습 니 다.대충 볼 수 밖 에 없 었 습 니 다.이번에 다시 한 번 분석 한 다음 에 제 가 한 번 실 현 했 습 니 다.저 에 게 반나절 이 걸 렸 습 니 다.하지만 아주 가치 가 있 습 니 다.진심으로 많은 것 을 배 웠 습 니 다.
우선 대체적인 논 리 를 살 펴 보 자.

(\/\/.*|\/\*[\S\s]+?\*\/) //
((["'])(?:\\.|[^\\
])*?\3) //
\b(break|continue|do|for|in|function|if|else|return|switch|this|throw|try|catch|finally|var|while|with|case|new|typeof|instance|delete|void)\b //
\b(Object|Array|String|Number|Boolean|Function|RegExp|Date|Math|window|document|navigator|location)\b //
\b(true|false)\b //
\b(null|undefined|NaN)\b // , 。
(?:[^\W\d]|\$)[\$\w]* //
(0[xX][0-9a-fA-F]+|\d+(?:\.\d+)?(?:[eE]\d+)?) // ( , )
(?:[^\)\]\}]|^)(\/(?!\*)(?:\\.|[^\\\/
])+?\/[gim]*) //
[\S\s] //
원문 에서 마지막[\S\s]에 대한 설명:우 리 는 모든 문자 에 일치 해 야 합 니 다.HTML 전의 가 필요 하기 때문이다.그리고 아래 에 상세 한 코드 가 있 습 니 다.
이것 은 매우 좋 은 문장 이다.나 는 앞 뒤 를 적어도 10 번 은 보지 못 했 고 이틀 전에 야 거의 완전히 이해 하지 못 했다.
그러나 이 코드 는 문자열 이 접 힌 줄 과 일치 하지 않 고 문자열 이 최적화 되 어 있 는 작은 흠 이 있 습 니 다.
그리고 숫자 매 칭 이 전면적 이지 않 으 면 0xff,12.34,1e3 등 몇 가지 유형 만 일치 할 수 있 습 니 다.예 를 들 어.123 12.3e+3 등 형식 은 일치 하지 않 습 니 다.그리고 키워드 순 서 는 조금 이라도 최적화 할 수 있 을 것 같 습 니 다.전통 적 인 NFA 엔진 은 왼쪽 에서 오른쪽으로 만 일치 하기 때문에 다음 분기 의 작업 을 중단 합 니 다.그래서 가장 자주 등장 하 는 키 워드 를 앞 에 놓 으 면 일부 성능 을 향상 시 킬 수 있다.마지막 으로 new RegExp 가 좋 습 니 다.이렇게 하면 코드 의 양 이 많은 코드 성능 이 향상 되 는 것 입 니 다.
다음은 제 정규 와 간단 한 demo 를 드 리 겠 습 니 다.사실은 차 탄산 코발트 소스 코드 에 대한 최적화 일 뿐이다.)먼저 정규 부분 보기:

(\/\/.*|\/\*[\s\S]*?\*\/) //
("(?:[^"\\]|\\[\s\S])*"|'(?:[^'\\]|\\[\s\S])*') //
\b(true|false|null|undefined|NaN)\b // , ,
\b(var|for|if|else|return|this|while|new|function|switch|case|typeof|do|in|throw|try|catch|finally|with|instance|delete|void|break|continue)\b // ,
\b(document|Date|Math|window|Object|location|navigator|Array|String|Number|Boolean|Function|RegExp)\b // ,
(?:[^\W\d]|\$)[\$\w]* //
(0[xX][0-9a-fA-F]+|\d+(?:\.\d+)?(?:[eE][+-]?\d+)?|\.\d+(?:[eE][+-]?\d+)?) // ,
(?:^|[^\)\]\}])(\/(?!\*)(?:\\.|[^\\\/
])+?\/[gim]*) // , , ,
[\s\S] //
불 과 빈 값 을 합 쳐 그룹 을 나 눈 후 정규 그룹 을 최적화 시 켜 그 보다 두 개의 그룹 을 줄 였 다.그 는 2,3 은 문자열 로 나 누 었 다.왜냐하면(")앞의 따옴표 가 잡 혔 고 나의 정 규 는 이렇게 하지 않 았 기 때문이다.이것(true|false|null|undefined|NaN)한 그룹 에 두 는 것 을 좋아 하지 않 는 다 면,나 누 어도 되 고,같은 그룹 인지 아 닌 지 는 착색 을 구분 하기 위 한 것 일 뿐 입 니 다.sublime text 아래 true|false|null|undefined|NaN 은 모두 같은 색 이 고 notepad+는 true|false 만 착색 되 었 습 니 다.저 는 그냥 하하 라 고 말 하고 싶 습 니 다.
됐어,하마터면 예 를 들 뻔 했 어.나 는 많은 사람들 이 이 를 보기 전에 이미 꺼 졌 거나 스크롤 바 만 내리 고 꺼 졌 다 고 믿는다.하지만 이 글 을 쓴 것 은 진지 하 게 보 는 친구 들 에 게 한 사람 만 보면 헛 되 지 않 을 것 이 라 고 생각 합 니 다.예:

//
/**
 *
 * @date 2014-05-12 22:24:37
 * @name
 */
var str1 = "123\"456";
var str2 = '123\'456';
var str3 = "123\
456";

var num = 123;
var arr = [12, 12.34, .12, 1e3, 1e+3, 1e-3, 12.34e3, 12.34e+3, 12.34e-3, .1234e3];
var arr = ["12", "12.34", '.12, 1e3', '1e+3, 1e-3', '12.34e3, 12.34e+3, 12.34e-3', ".1234e3"];
var arr = [/12", "12.34/, /"12\/34"/];

for (var i=0; i<1e3; i++) {
  var node = document.getElementById("a"+i);
  arr.push(node);
}

function test () {
  return true;
}
test();

 

(function(window, undefined) {
    var _re_js = new RegExp('(\\/\\/.*|\\/\\*[\\s\\S]*?\\*\\/)|("(?:[^"\\\\]|\\\\[\\s\\S])*"|\'(?:[^\'\\\\]|\\\\[\\s\\S])*\')|\\b(true|false|null|undefined|NaN)\\b|\\b(var|for|if|else|return|this|while|new|function|switch|case|typeof|do|in|throw|try|catch|finally|with|instance|delete|void|break|continue)\\b|\\b(document|Date|Math|window|Object|location|navigator|Array|String|Number|Boolean|Function|RegExp)\\b|(?:[^\\W\\d]|\\$)[\\$\\w]*|(0[xX][0-9a-fA-F]+|\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?|\\.\\d+(?:[eE][+-]?\\d+)?)|(?:^|[^\\)\\]\\}])(\\/(?!\\*)(?:\\\\.|[^\\\\\\/\
])+?\\/[gim]*)|[\\s\\S]', 'g');

    function prettify(node) {
        var code = node.innerHTML.replace(/\r
|[\r
]/g, "
").replace(/^\s+|\s+$/g, "");
        code = code.replace(_re_js, function() {
            var s, a = arguments;
            for (var i = 1; i <= 7; i++) {
                if (s = a[i]) {
                    s = htmlEncode(s);
                    switch (i) {
                        case 1: // com
                            return '<span class="com">' + s + '</span>';
                        case 2: // str
                            return '<span class="str">' + s + '</span>';
                        case 3: //true|false|null|undefined|NaN val
                            return '<span class="val">' + s + '</span>';
                        case 4: // kwd
                            return '<span class="kwd">' + s + '</span>';
                        case 5: // obj
                            return '<span class="obj">' + s + '</span>';
                        case 6: // num
                            return '<span class="num">' + s + '</span>';
                        case 7: // reg
                            return htmlEncode(a[0]).replace(s, '<span class="reg">' + s + '</span>');
                    }
                }
            }
            return htmlEncode(a[0]);
        });
        code = code.replace(/(?:\s*\*\s*|(?: )*\*(?: )*)(@\w+)\b/g, ' * <span class="comkey">$1</span>') //
                   .replace(/(\w+)(\s*\(|(?: )*\()|(\w+)(\s*=\s*function|(?: )*=(?: )*function)/g, '<span class="func">$1</span>$2') //
        return code;
    }


    function htmlEncode(str) {
        var i, s = {
                //"&": /&/g,
                """: /"/g,
                "'": /'/g,
                "<": //g,
                "<br>": /
/g,
                " ": / /g,
                "  ": /\t/g
            };
        for (i in s) {
            str = str.replace(s[i], i);
        }
        return str;
    }

    window.prettify = prettify;
})(window);

너 희 는 아래 의 코드 로 테스트 를 진행 할 수 있다.
코드:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>test</title>
    <style>
    /* */
    *{font-size:12px;}
    code{word-break:break-all;}

    .com {color:#008000;} /* */
    .comkey {color:#FFA500;} /* */
    .str {color:#808080;} /* */
    .val {color:#000080;} /* true|false|null|undefined|NaN */
    .kwd {color:#000080;font:bold 12px 'comic sans ms', sans-serif;} /* */
    .obj {color:#000080;} /* */
    .num {color:#FF0000;} /* */
    .reg {color:#8000FF;} /* */
    .func {color:#A355B9;} /* */
    </style>
</head>
<body>

<code id="regdemon">
//
/**
 *
 * @date 2014-05-12 22:24:37
 * @name
 */
var str1 = "123\"456";
var str2 = '123\'456';
var str3 = "123\
456";

var num = 123;
var arr = [12, 12.34, .12, 1e3, 1e+3, 1e-3, 12.34e3, 12.34e+3, 12.34e-3, .1234e3];
var arr = ["12", "12.34", '.12, 1e3', '1e+3, 1e-3', '12.34e3, 12.34e+3, 12.34e-3', ".1234e3"];
var arr = [/12", "12.34/, /"12\/34"/];

for (var i=0; i<1e3; i++) {
    var node = document.getElementById("a"+i);
    arr.push(node);
}

function test () {
    return true;
}
test();

 

(function(window, undefined) {
    var _re_js = new RegExp('(\\/\\/.*|\\/\\*[\\s\\S]*?\\*\\/)|("(?:[^"\\\\]|\\\\[\\s\\S])*"|\'(?:[^\'\\\\]|\\\\[\\s\\S])*\')|\\b(true|false|null|undefined|NaN)\\b|\\b(var|for|if|else|return|this|while|new|function|switch|case|typeof|do|in|throw|try|catch|finally|with|instance|delete|void|break|continue)\\b|\\b(document|Date|Math|window|Object|location|navigator|Array|String|Number|Boolean|Function|RegExp)\\b|(?:[^\\W\\d]|\\$)[\\$\\w]*|(0[xX][0-9a-fA-F]+|\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?|\\.\\d+(?:[eE][+-]?\\d+)?)|(?:^|[^\\)\\]\\}])(\\/(?!\\*)(?:\\\\.|[^\\\\\\/\
])+?\\/[gim]*)|[\\s\\S]', 'g');

    function prettify(node) {
        var code = node.innerHTML.replace(/\r
|[\r
]/g, "
").replace(/^\s+|\s+$/g, "");
        code = code.replace(_re_js, function() {
            var s, a = arguments;
            for (var i = 1; i <= 7; i++) {
                if (s = a[i]) {
                    s = htmlEncode(s);
                    switch (i) {
                        case 1: // com
                            return '<span class="com">' + s + '</span>';
                        case 2: // str
                            return '<span class="str">' + s + '</span>';
                        case 3: //true|false|null|undefined|NaN val
                            return '<span class="val">' + s + '</span>';
                        case 4: // kwd
                            return '<span class="kwd">' + s + '</span>';
                        case 5: // obj
                            return '<span class="obj">' + s + '</span>';
                        case 6: // num
                            return '<span class="num">' + s + '</span>';
                        case 7: // reg
                            return htmlEncode(a[0]).replace(s, '<span class="reg">' + s + '</span>');
                    }
                }
            }
            return htmlEncode(a[0]);
        });
        code = code.replace(/(?:\s*\*\s*|(?:&nbsp;)*\*(?:&nbsp;)*)(@\w+)\b/g, '&nbsp;*&nbsp;<span class="comkey">$1</span>') //
                   .replace(/(\w+)(\s*\(|(?:&nbsp;)*\()|(\w+)(\s*=\s*function|(?:&nbsp;)*=(?:&nbsp;)*function)/g, '<span class="func">$1</span>$2') //
        return code;
    }


    function htmlEncode(str) {
        var i, s = {
                //"&amp;": /&/g,
                "&quot;": /"/g,
                "&#039;": /'/g,
                "&lt;": /</g,
                "&gt;": />/g,
                "<br>": /
/g,
                "&nbsp;": / /g,
                "&nbsp;&nbsp;": /\t/g
            };
        for (i in s) {
            str = str.replace(s[i], i);
        }
        return str;
    }

    window.prettify = prettify;
})(window);
</code>

<script>
(function(window, undefined) {
    var _re_js = new RegExp('(\\/\\/.*|\\/\\*[\\s\\S]*?\\*\\/)|("(?:[^"\\\\]|\\\\[\\s\\S])*"|\'(?:[^\'\\\\]|\\\\[\\s\\S])*\')|\\b(true|false|null|undefined|NaN)\\b|\\b(var|for|if|else|return|this|while|new|function|switch|case|typeof|do|in|throw|try|catch|finally|with|instance|delete|void|break|continue)\\b|\\b(document|Date|Math|window|Object|location|navigator|Array|String|Number|Boolean|Function|RegExp)\\b|(?:[^\\W\\d]|\\$)[\\$\\w]*|(0[xX][0-9a-fA-F]+|\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?|\\.\\d+(?:[eE][+-]?\\d+)?)|(?:^|[^\\)\\]\\}])(\\/(?!\\*)(?:\\\\.|[^\\\\\\/\
])+?\\/[gim]*)|[\\s\\S]', 'g');

    function prettify(node) {
        var code = node.innerHTML.replace(/\r
|[\r
]/g, "
").replace(/^\s+|\s+$/g, "");
        code = code.replace(_re_js, function() {
            var s, a = arguments;
            for (var i = 1; i <= 7; i++) {
                if (s = a[i]) {
                    s = htmlEncode(s);
                    switch (i) {
                        case 1: // com
                            return '<span class="com">' + s + '</span>';
                        case 2: // str
                            return '<span class="str">' + s + '</span>';
                        case 3: //true|false|null|undefined|NaN val
                            return '<span class="val">' + s + '</span>';
                        case 4: // kwd
                            return '<span class="kwd">' + s + '</span>';
                        case 5: // obj
                            return '<span class="obj">' + s + '</span>';
                        case 6: // num
                            return '<span class="num">' + s + '</span>';
                        case 7: // reg
                            return htmlEncode(a[0]).replace(s, '<span class="reg">' + s + '</span>');
                    }
                }
            }
            return htmlEncode(a[0]);
        });
        code = code.replace(/(?:\s*\*\s*|(?:&nbsp;)*\*(?:&nbsp;)*)(@\w+)\b/g, '&nbsp;*&nbsp;<span class="comkey">$1</span>') //
                   .replace(/(\w+)(\s*\(|(?:&nbsp;)*\()|(\w+)(\s*=\s*function|(?:&nbsp;)*=(?:&nbsp;)*function)/g, '<span class="func">$1</span>$2') //
        return code;
    }


    function htmlEncode(str) {
        var i, s = {
                //"&amp;": /&/g,
                "&quot;": /"/g,
                "&#039;": /'/g,
                "&lt;": /</g,
                "&gt;": />/g,
                "<br>": /
/g,
                "&nbsp;": / /g,
                "&nbsp;&nbsp;": /\t/g
            };
        for (i in s) {
            str = str.replace(s[i], i);
        }
        return str;
    }

    window.prettify = prettify;
})(window);

var code = document.getElementById("regdemon");
code.innerHTML = prettify(code);
</script>
</body>
</html>

콧수염 형 과 차 탄산 코발트 두 가지 사고방식 을 결합 한 결과 지금 은 비교적 완벽 해 졌 다.호환성 같은 것 은 아직 테스트 를 하지 않 았 고 테스트 할 필요 도 없다.나 도 각종 문법의 하 이 라 이 트 를 스스로 쓸 생각 은 없다.너무 피곤 하 다.

좋은 웹페이지 즐겨찾기