【问题标题】:Regular expression using negative lookbehind not working in Notepad++使用负后向的正则表达式在 Notepad++ 中不起作用
【发布时间】:2013-06-24 23:17:13
【问题描述】:

我有一个源文件,其中包含数百个字符串flecha.jpgflecha1.jpg,但我需要找到任何其他.jpg 图像的出现(即casa.jpgmoto.jpg,等等)

我尝试过使用带有负向回溯的正则表达式,如下所示:

(?<!flecha|flecha1).jpg

但它不起作用! Notepad++ 只是说它是一个无效的正则表达式。

我在其他地方尝试过正则表达式,它可以工作,here is an example 所以我猜这是 NPP 处理正则表达式或lookbehinds/lookaheads 语法的问题。

那么我怎样才能在 NPP 中实现相同的正则表达式结果呢?

如果有用,我使用的是 Notepad++ 6.3 Unicode

另外,如果您这么好心,那么实现相同目标但使用可选数字(在这种情况下只有“1”)作为我的字符串后缀的语法是什么? (即使它在 NPP 中不起作用,只是要知道)...

我尝试了(?&lt;!flecha[1]?).jpg,但它不起作用。它应该与其他正则表达式一样工作,请参见此处 (RegExr)

【问题讨论】:

    标签: regex notepad++ regex-lookarounds negative-lookbehind


    【解决方案1】:

    Notepad++ 似乎没有实现可变长度的look-behinds(某些工具会发生这种情况)。一种解决方法是使用多个固定长度的后视:

    (?<!flecha)(?<!flecha1)\.jpg
    

    如您所见,the matches are the same。但这适用于 npp。

    请注意,我转义了 .,因为您正在尝试匹配扩展名,所以您想要的是文字 .。按照你的方式,它是一个通配符 - 可以是任何字符。

    关于额外的问题,不幸的是,因为我们不能有可变长度的后视,所以不可能有可选的后缀(数字)而没有多个后视。

    【讨论】:

    • 在更明亮的音符上,您可以使用[0-9]\d 或其他类似的,只要每个后视的长度保持固定:(?&lt;!flecha)(?&lt;!flecha[1-3])\.jpg
    • 再挖一点,我们的想法得到了确认:Notepad++ 使用 Boost 作为正则表达式实现,而 Boost Regex 只支持固定长度的后视。
    • 太棒了!对你的回答有点怀疑;在这种情况下,没有可变长度后视的限制仅适用于 Npp?或者也适用于正则表达式和其他工具?即在其他工具中,我也许可以使用可变长度的后视?或者它是一个正则表达式限制,在其他任何地方都不起作用?
    • 一般来说,这不是对正则表达式的限制。我的意思是,一种工具/语言可以有可变长度的后视,它只取决于它们。对于现在的 NPP 来说,这是一个限制。看,6.3 之前的 npp 根本没有后视。这对他们来说是相当新鲜的。其他工具有自己的历史。 Perl 版本 5 及更低版本也没有可变长度的后视,在最近的版本中它们有。 JavaScript 根本没有后视功能,而 Java 有可变长度的后视功能,可以事先知道最大长度((?&lt;=[a|abc]) 可以,但(?&lt;=a|.*) 不行)。
    • @acdcjunior 您可能想在您的答案中添加有关使用 Boost 的内容。
    【解决方案2】:

    解决记事本++中可变长度负后向限制的问题

    这里给出了几种在 Notepad++(或任何具有相同限制的正则表达式引擎)中解决此限制的策略

    定义问题

    Notepad++ 不支持使用可变长度的否定后向断言,如果有一些变通方法会很好。让我们考虑原始问题中的示例,但假设我们希望避免出现名为flecha 的文件在flecha 之后有任何 个数字,并且在flecha 之前有任何字符。在这种情况下,使用可变长度负向后查找的正则表达式看起来像 (?&lt;!flecha[0-9]*)\.jpg

    本例中我们不想匹配的字符串

    • flecha.jpg
    • flecha1.jpg
    • flecha00501275696.jpg
    • aflecha.jpg
    • img_flecha9.jpg
    • abcflecha556677.jpg

    战略

    1. 插入临时标记

      首先对您想避免使用的实例执行查找和替换 - 在我们的例子中,是 flecha[0-9]*\.jpg 的实例。插入一个特殊的标记以形成一个不会出现在其他任何地方的图案。对于这个例子,我们将在.jpg 之前插入一个额外的.,假设..jpg 没有出现在其他地方。所以我们这样做:

      查找:(flecha[0-9]*)(\.jpg)

      替换为:$1.$2

      现在您可以使用\w+\.jpg(?&lt;!\.)\.jpg 之类的简单正则表达式在文档中搜索所有其他.jpg 文件名,然后对它们做您想做的事情。完成后,执行最后的查找和替换操作,将所有 ..jpg 实例替换为 .jpg,以删除临时标记。

    2. 使用否定的前瞻断言

      可以使用否定的前瞻断言来确保您没有匹配不需要的文件名:

      (?&lt;!\S)(?!\S*flecha\d*\.jpg)\S+\.jpg

      分解:

      • (?&lt;!\S) 通过断言您的匹配项前面没有非空白字符来确保您的匹配项从文件名的开头而不是中间开始。
      • (?!\S*flecha\d*\.jpg) 确保匹配的内容不包含我们想要避免的模式
      • \S+\.jpg 是实际匹配的——一串非空白字符,后跟 .jpg
    3. 使用多个固定长度的负向回溯

      这是一种快速(但不那么优雅)的解决方案,适用于您不想匹配的模式具有可能的长度数量较少的情况。

      例如,如果我们知道flecha 后面最多只能跟三位数字,那么我们的正则表达式可以是:

      (?&lt;!flecha)(?&lt;!flecha[0-9])(?&lt;!flecha[0-9][0-9])(?&lt;!flecha[0-9][0-9][0-9])\.jpg

    【讨论】:

    • 你的策略 3 绝对拯救了我的一天。我知道发送感谢不是 cmets 的预期目的,但我想无论如何我都会发帖。谢谢@JoshWithee!对于其他正在努力解决可变长度前瞻/后视的人,我建议尝试这种不优雅但有效的方法。
    • 策略 1 帮助了我。谢谢。
    【解决方案3】:

    您是否知道您只是匹配(在消费的意义上)扩展名 (.jpg)?我想你想匹配整个文件名,不是吗?使用前瞻更容易做到这一点:

    \b(?!flecha1?\b)\w+\.jpg
    

    第一个\b 将匹配锚定到名称的开头(假设它确实是我们正在查看的文件名)。然后(?!flecha1?\b) 断言名称不是flechaflecha1。完成后,\w+ 继续使用该名称。然后\.jpg 抓住分机结束比赛。

    【讨论】:

    • 如您所见,我只想匹配 .jpg 扩展名。我只想在源文件中查找任何其他图像,并且我不需要知道它们的文件名,只要它们出现就行了。不过谢谢!答案肯定对未来有用=)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-03
    • 2019-01-30
    • 1970-01-01
    • 2023-03-13
    • 2018-10-05
    相关资源
    最近更新 更多