容忍RegEx中的某些字符

时间:2018-03-29 14:42:30

标签: javascript regex string-parsing null-character

我正在编写一个消息格式化解析器,它具有解析链接的能力(以及其他)。此特定情况需要解析<url|linkname>中的链接,并仅使用linkname替换该文本。这里的问题是,urllinkname可能包含\1\2个字符,但在任何顺序中都可以包含linkname([^\n+])个字符(尽管最多只有一个)。我想匹配模式,但保持&#34;无效&#34;字符。此问题解决了url,因为该模式的一部分只是[\1\2],但.replace(/\1|\2/g, "")片段与更复杂的模式相匹配,更具体地来说是{[\1\2]{0,2}的URL验证模式3}}。手动修改整个模式以容忍\1\2到处都是不容易的,我需要这种模式来保留这些字符,因为它们用于跟踪目的(所以我不能只是{{1}匹配前)。

如果无法进行此类匹配,是否有一些自动方式可靠地修改RegExp以在每个字符匹配之间添加[chars],将url添加到所有is.js匹配等

这是取自/(?:(?:https?|ftp):\/\/)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/\S*)?/i 的{​​{1}}模式:

<url|linkname>

此模式已根据我的目的和let namedUrlRegex = /<((?:(?:https?|ftp):\/\/)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/\S*)?)\|([^\n]+)>/ig; 格式进行了调整,如下所示:

...

使用它的代码在这里:is.js

澄清示例(namedUrlRegex表示上面的$2变量,linkname是捕获Current behavior: "<googl\1e.com|Google>".replace(..., "$2") // "<googl\1e.com|Google>" WRONG "<google.com|Goo\1gle>".replace(..., "$2") // "Goo\1gle" CORRECT "<not_\1a_url|Google>".replace(..., "$2") // "<not_\1a_url|Google>" CORRECT Expected behavior: "<googl\1e.com|Google>".replace(..., "$2") // "Google" (note there is no \1) "<google.com|Goo\1gle>".replace(..., "$2") // "Goo\1gle" "<not_\1a_url|Google>".replace(..., "$2") // "<not_\1a_url|Google>" 的捕获组:

\1
  

请注意,\2的相同规则适用于\1\2\1...\2\2...\1\1

     

上下文:用于将WYSIWYG编辑器中的字符串规范化为它将显示的长度/内容,保留当前选择的位置(由\2<url|linkname>表示,以便它解析后可以恢复)。如果&#34;插入&#34;完全删除(例如,如果光标在链接的URL中),它将选择整个字符串。除了选择在url片段中开始或结束时,一切都按预期工作。

     

编辑以澄清:我想要更改字符串中的细分如果它遵循url格式\1匹配的网址格式(容忍\2linkname)和\n由非<...|...>个字符组成。如果在not_a_url字符串中未满足此条件,则应按照上面的{{1}}示例将其保留为未更改

1 个答案:

答案 0 :(得分:0)

我最终制作了一个符合所有&#34;符号的RegEx&#34;在表达中。其中一个怪癖是,它希望转义=!(?:...)个字符,即使在(?=...)(?!...),{{1}之外也是如此表达。这可以通过在处理之前转义它们来解决。

Fiddle

let r = /(\\.|\[.+?\]|\w|[^\\\/\[\]\^\$\(\)\?\*\+\{\}\|\+\:\=\!]|(\{.+?\}))(?:((?:\{.+?\}|\+|\*)\??)|\??)/g;

let url = /((?:(?:https?|ftp):\/\/)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/\S*)?)/

function tolerate(regex, insert) {
    let first = true;
        // convert to string
    return regex.toString().replace(/\/(.+)\//, "$1").
        // escape :=!
        replace(/((?:^|[^\\])\\(?:\\)*\(\?|[^?])([:=!]+)/g, (m, g1, g2) => g1 + (g2.split("").join("\\"))).
        // substitute string
        replace(r, function(m, g1, g2, g3, g4) {
            // g2 = {...} multiplier (to prevent matching digits as symbols)
            if (g2) return m;
            // g3 = multiplier after symbol (must wrap in parenthesis to preserve behavior)
            if (g3) return "(?:" + insert + g1 + ")" + g3;
            // prevent matching tolerated characters at beginning, remove to change this behavior
            if (first) {
                first = false;
                return m;
            }
            // insert the insert
            return insert + m;
        }
    );
}

alert(tolerate(url, "\1?\2?"));