Regex Javascript 如何模仿 PHP Regex 的 Negative Lookback



我有以下正则表达式(?<!#)hazcons?0和我的示例测试消息。我遇到的麻烦是从PHP将其转换为Javascript,因为Javascript不支持负面的回溯。我想匹配任何hazcon 0hazcon0,但忽略任何#hazcon0#hazcon 0实例。

#hazcon0 <-不匹配

#hazcon 0 <-不匹配

hazcon 0

hazcon 0

blah blah blah blah hazcon0 blah blah

blah blah blah blah hazcon 0 blah blah

如果有更好的方法,我想了解!

不要要求没有八角形,而是要求有开头(^)或八角形以外的字符([^#]

(^|[^#])hazcons?0

反向字符串方法在特定情况下可能会失败(例如,当您需要匹配不在左括号之前的连续双撇号时)。使用负面回溯的最可靠方法是使用带有一些扩展XRegExp库。

// Simulating infinite-length leading lookbehind in JavaScript. Uses XRegExp.
// Captures within lookbehind are not included in match results. Lazy
// repetition in lookbehind may lead to unexpected results.
(function (XRegExp) {
    function prepareLb(lb) {
        // Allow mode modifier before lookbehind
        var parts = /^((?:(?[w$]+))?)(?<([=!])([sS]*))$/.exec(lb);
        return {
            // $(?!s) allows use of (?m) in lookbehind
            lb: XRegExp(parts ? parts[1] + "(?:" + parts[3] + ")$(?!\s)" : lb),
            // Positive or negative lookbehind. Use positive if no lookbehind group
            type: parts ? parts[2] === "=" : !parts
        };
    }
    XRegExp.execLb = function (str, lb, regex) {
        var pos = 0, match, leftContext;
        lb = prepareLb(lb);
        while (match = XRegExp.exec(str, regex, pos)) {
            leftContext = str.slice(0, match.index);
            if (lb.type === lb.lb.test(leftContext)) {
                return match;
            }
            pos = match.index + 1;
        }
        return null;
    };
    XRegExp.testLb = function (str, lb, regex) {
        return !!XRegExp.execLb(str, lb, regex);
    };
    XRegExp.searchLb = function (str, lb, regex) {
        var match = XRegExp.execLb(str, lb, regex);
        return match ? match.index : -1;
    };
    XRegExp.matchAllLb = function (str, lb, regex) {
        var matches = [], pos = 0, match, leftContext;
        lb = prepareLb(lb);
        while (match = XRegExp.exec(str, regex, pos)) {
            leftContext = str.slice(0, match.index);
            if (lb.type === lb.lb.test(leftContext)) {
                matches.push(match[0]);
                pos = match.index + (match[0].length || 1);
            } else {
                pos = match.index + 1;
            }
        }
        return matches;
    };
    XRegExp.replaceLb = function (str, lb, regex, replacement) {
        var output = "", pos = 0, lastEnd = 0, match, leftContext;
        lb = prepareLb(lb);
        while (match = XRegExp.exec(str, regex, pos)) {
            leftContext = str.slice(0, match.index);
            if (lb.type === lb.lb.test(leftContext)) {
                // Doesn't work correctly if lookahead in regex looks outside of the match
                output += str.slice(lastEnd, match.index) + XRegExp.replace(match[0], regex, replacement);
                lastEnd = match.index + match[0].length;
                if (!regex.global) {
                    break;
                }
                pos = match.index + (match[0].length || 1);
            } else {
                pos = match.index + 1;
            }
        }
        return output + str.slice(lastEnd);
    };
}(XRegExp));
// DEMO
document.body.innerHTML = "hazcon 0: " + XRegExp.testLb("hazcon 0", "(?<!#)", XRegExp("\bhazcon\s*0\b"));
document.body.innerHTML += "<br/>hazcon0: " + XRegExp.testLb("hazcon0", "(?<!#)", XRegExp("\bhazcon\s*0\b"));
document.body.innerHTML += "<br/>#hazcon0: " + XRegExp.testLb("#hazcon0", "(?<!#)", XRegExp("\bhazcon\s*0\b"));
document.body.innerHTML += "<br/>#hazcon 0: " + XRegExp.testLb("#hazcon 0", "(?<!#)", XRegExp("\bhazcon\s*0\b"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/xregexp/2.0.0/xregexp-all-min.js"></script>

请参阅 JavaScript Regex Lookbehind Redux

缩小和压缩后不到 0.5 KB。它提供了一组函数,使模拟前导回溯变得简单:
    
XRegExp.execLb     
XRegExp.testLb     
XRegExp.searchLb     
XRegExp.matchAllLb     
XRegExp.replaceLb

最新更新