Regex 为什么';这不是正则表达式的前瞻性工作吗?

Regex 为什么';这不是正则表达式的前瞻性工作吗?,regex,iis,url-rewriting,negative-lookahead,regex-lookarounds,Regex,Iis,Url Rewriting,Negative Lookahead,Regex Lookarounds,我正在设计一个正则表达式,用于一些IIS Url重写。其目的是捕获以下URL: 不只是根目录中的一个文件(通过包含句点来标识),以及 不包含查询字符串,并且 不属于特定的子目录集,特别是“帐户”和“公共” 我当前的正则表达式如下所示: ^(?!(Account)|(Public))([^./]+)(/[^?]*)?$ 与以下测试集一起使用: file.aspx Account/otherfile.aspx Public/otherfile.aspx otherfolder1/otherfile

我正在设计一个正则表达式,用于一些IIS Url重写。其目的是捕获以下URL:

  • 不只是根目录中的一个文件(通过包含句点来标识),以及
  • 不包含查询字符串,并且
  • 不属于特定的子目录集,特别是“帐户”和“公共”
  • 我当前的正则表达式如下所示:

    ^(?!(Account)|(Public))([^./]+)(/[^?]*)?$
    
    与以下测试集一起使用:

    file.aspx
    Account/otherfile.aspx
    Public/otherfile.aspx
    otherfolder1/otherfile.aspx?stuff=otherstuff
    otherfolder2/otherfolder/otherfile.aspx
    otherfolder3/
    otherfolder4
    
    我的正则表达式正确地忽略了前两种情况,但它仍然与第三种情况匹配。这里的前瞻有什么问题?

    正如所报告的,RegexPal中这些测试的问题是,运行多行测试可以将多行组合在一起,以创建一个单独的匹配,否则它们不应该

    正则表达式就其设计目的而言是很好的。实际上,这太过分了。对于IIS重写和重定向,如果使用,则可以选择指定其将接受或不接受匹配的条件。其中一些选择包括:

    • 项不是物理文件
    • 项不是物理目录
    • 项目与辅助模式不匹配(或不匹配)

    这些将比消极前瞻更完全地达到预期效果。

    也许您想要使用
    ^(?!Account | Public)([^\.\/]+\/[^\?]*)$
    regex

    请看这里:

    那么正确的正则表达式模式应该是
    ^(?!Account | Public)([^\.\/]+\/[^\?\n]*)$


    [更新]

    文件名不必在其名称中包含点
    ,另一方面,文件夹/目录名可能在其名称中包含点
    ,但如果您想在第7行也有一个正匹配,那么您应该使用模式
    ^(?!Account | Public)([^\.\/]+(?:\/[^\?]*.[^\.\.\?]))$
    并且它也应该作为RegExPal模式工作


    看看这里:

    我忍不住想想出一些可以在RegExPal中使用的东西(没有成功-编辑:刚刚验证,这在RegExPal中确实有效),但我想我会把它作为另一种方法扔到那里,做你需要的事情,这可能更容易理解:

    ^(?!Account|Public|[a-zA-Z_0-9]+\.)[a-zA-Z_0-9/.]+$
    
    解释:

    ^                   # start
    (?!                 # open a negative lookahead
    Account|Public|     # ignore both Account and Public
    [a-zA-Z_0-9]+\.     # ignore files in root (i.e., letters/numbers, followed by period)
    )                   # close negative lookahead
    [a-zA-Z_0-9/.]+     # now match anything with letters/numbers, periods and slashes, but no '?' (ignores URLs with query string)
    $                   # end
    

    RegexPal很困惑,但真正的问题是regex的设计不正确

    不确定您想做什么,但在使用多行模式和锚定时
    ^$

    在正则表达式中,除非您专门这样设计,否则必须注意不要
    溢出锚。这适用于贪婪/非贪婪量词。
    如果将消极的前瞻性条件加入到组合中,情况会变得更糟

    在这种情况下,它导致RegexPal发疯,显然在
    ^

    没有重新评估^。不过,这可能不是JavaScript问题

    将not newline添加到消费类可以解决所有问题。它必须是
    添加到两个类中

    ^(?!Account|Public)[^./\n]+(?:/[^?\n]*)?$
    

    这在RegexPal中,它对我来说就像预期的那样工作。您只希望示例中的最后3个匹配,对吗?对。对我来说,它匹配2,3,5,6和7。好吧,这真的很奇怪。在我的实际测试中,我把我的例子隔开,在每个例子之间放一个空白行。如果我删除空白行,它会给出想要的结果。是的,我不确定到底发生了什么。值得一提的是,我在C#中做了一个快速测试,它也产生了正确的结果。只是为了记录
    (?!(Account)|(Public))
    是一个消极的前瞻,而不是一个落后。而
    Account
    Public
    周围的括号不做任何事情,因为前瞻不会参与匹配。我相信应该是这样的:
    (?!Account | Public)
    。否则,正则表达式似乎确实起作用,尽管在第7项上不匹配的正则表达式中不起作用。另外,我非常确定您永远不需要逃逸
    /
    ,也不需要在
    []
    @JeffreyBlake中逃逸
    /
    ——逃逸
    /
    更安全,而且它对于regex来说是相当标准的,因为有些语言需要(例如Perl)。除此之外,你为什么想要第七项来匹配呢?文件名中不需要有点。但是如果这是你正在寻找的,那么看看我上面更新的答案。感谢您考虑我的答案。我认为这要求root中的文件以句点结尾,这是不正确的。这段时间实际上永远不会结束;通常有三个角色,但有时多一些,有时少一些。@JeffreyBlake:不,这不是lookaheads的工作原理。因为它是一个消极的前瞻,一旦它遇到一个周期,它匹配并失败,这就是你想要的。这段时间不一定要结束。JeffreyBlake:在阅读了@sln的答案后,我可以看到RegExPal上发生了什么。您的正则表达式实际上是将示例输入的最后三行匹配为一个匹配(即,所有三行构成一个匹配),并且除非选中“多行锚定”,否则正则表达式不会显示(颜色)匹配。sln的回答解释了原因。无论是我的答案还是sln都可以满足您的需要,但您的正则表达式可能会在某个时候失败,因为它肯定超过了行尾。sln的答案可能更好,因为它比我的更一般,但我会犹豫在生产环境中使用你的答案。+1解决了这个问题。不过,我正在讨论接受哪个答案。这个驱动的重定向系统实际上需要根文件夹和剩余的文件结构是独立的匹配项,它可以从中构造结果替换url。这让我想到,我原来拥有的可能是最好的(去掉了“展望”中的额外参数)。+1解释了问题发生的原因。实际上,换行问题不是问题,因为重定向系统正在处理单个URL。