【问题标题】:Lookahead regex pattern in javascriptjavascript中的前瞻正则表达式模式
【发布时间】:2014-09-04 12:14:30
【问题描述】:

我正在尝试从以下字符串进行匹配:

[[NOTE]]This is my note.[[NOTE]]

以下模式:

This is my note.

由于我不能使用前瞻,这是我目前的尝试:

[^\[\[NOTE\]\]](.*)[^\[\[NOTE\]\]]

但还是不行。

【问题讨论】:

    标签: javascript regex


    【解决方案1】:

    使用您在第一个捕获组中捕获的内容:

    var re = /\[\[NOTE]](.*?)\[\[NOTE]]/; 
    var str = '[[NOTE]]This is my note.[[NOTE]]';
    var m = re.exec(str);
    
    console.log(m[1])
    // This is my note.
    

    通过添加 ? 避免匹配 This a note[[NOTE]][[NOTE]]Also note 使您的 * 量词变得懒惰

    [[NOTE]]This a note[[NOTE]][[NOTE]]Also note[[NOTE]]
    

    【讨论】:

      【解决方案2】:

      您当前的正则表达式不起作用。几点:

      • 您将所有内容都放在一个字符类中:[^...]。它使得正则表达式匹配列表中的一个字符,这 不是 在这种情况下你想要的。删除它们。

      • 如果我正确理解了您的问题,您实际上并不需要环顾表达式来表达您正在尝试做的事情。 JavaScript确实支持前瞻;但它不支持lookbehinds。

      假设您正在尝试匹配开始和结束 [[NOTE]] 标记之间的文本,为什么不直接使用:

      \[\[NOTE\]\]([^\[\]]+)\[\[NOTE\]\]
      

      解释:

      • \[\[NOTE\]\] 匹配 [[NOTE]]

      • [^\[\]]+ 是一个否定字符类,它匹配一个或多个不是[] 的字符。

      【讨论】:

        【解决方案3】:

        您需要在您的正则表达式中转义左 [ 括号,还必须从字符类中删除 ^ 符号。

        \[\[NOTE]]((?:(?!\[\[NOTE]]).)*)\[\[NOTE]]
        

        DEMO

        > var re = /\[\[NOTE]]((?:(?!\[\[NOTE]]).)*)\[\[NOTE]]/g;
        undefined
        > var str = '[[NOTE]]This is my note.[[NOTE]]';
        undefined
        > var m;
        undefined
        > while ((m = re.exec(str)) != null) {
        ... console.log(m[1]);
        ... }
        This is my note.
        

        【讨论】:

        • 很好奇您为什么要使用((?:(?!\[\[NOTE]]).)*) 来捕获中间的文本。这肯定比其他替代方案慢,主要是因为它需要检查每个位置并查看它后面是否没有[[NOTE]]。为什么不使用否定字符类呢?
        • 你为什么使用\[\[NOTE\]\]([^\[\]]+)\[\[NOTE\]\],只是.*? 可以完成这项工作?
        • 因为它比.*? 更具体。如果您查看您发布的演示链接上的正则表达式调试器,您会发现您的正则表达式仅在 95 步 后才能找到匹配项,而我的仅需要 21 步。
        • @AmalMurali 为什么你不赞成我的回答?如果内容中间包含[,您的答案将不起作用。 [[NOTE]]This is my [note.[[NOTE]] OP 想要两个 [[NOTE]] 之间的文本
        【解决方案4】:

        首先,javascript 中的前瞻是fully supported(后瞻不是)。

        在你的正则表达式[^\[\[NOTE\]\]](.*)[^\[\[NOTE\]\]]

        • [] 只能检查单个字符的存在。例如,[^cat] 匹配任何不是cat 的字符。
        • 在中间你需要一个lazy quantifier:*?,如果它是一个长模板,则只匹配第一个结束标记。

        没有这些错误,它可以完美运行:\[\[NOTE\]\](.*?)\[\[NOTE\]\]

        • 它与[[NOTE]]This is my note.[[NOTE]] 匹配,并与第一个捕获组This is my note. 匹配。

        另一种捕获开始令牌并使用backreference 作为结束令牌的选项:

        • (\[\[NOTE\]\])(.*?)\1

        或者您可以使用positive lookahead

        • (\[{2,2}NOTE\]{2,2})(.*?)(?=\1)
          所以正则表达式只会匹配[[NOTE]]This is my note.

        如果你想使用不同的结束标签,例如[[/NOTE]],那么你可以使用类似这样的东西:

        • \[{2,2}(NOTE)\]{2,2}(.*?)(?=\[{2,2}\/\1\]{2,2})
        • \[{2,2}(NOTE)\]{2,2}(.*?)\[{2,2}\/\1\]{2,2}

        如果你想使用嵌套的开闭语句,那么唯一的选择就是逐个标记解析模板标记。通过 perl 兼容的正则表达式,有一个叫做 recursive regex 的东西。有了它,解析嵌套的开闭模板就容易多了,但该功能在 javascript 中不可用......如果您不想支持嵌套结构,那么实际的正则表达式就足够了。使用第一个捕获组而不是完整匹配,仅此而已。 Lookaround 没必要……

        顺便说一句。我强烈建议您使用现有的模板系统,我们不需要另一个...What Javascript Template Engines you recommend?

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-09-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多