如何使用负前瞻(NOT lookbehind)来匹配在特定位置不包含给定子字符串的字符串?

Posted

技术标签:

【中文标题】如何使用负前瞻(NOT lookbehind)来匹配在特定位置不包含给定子字符串的字符串?【英文标题】:How to use negative lookahead (NOT lookbehind) to match a string that does NOT contain a given substring at a specific position? 【发布时间】:2021-11-26 19:55:48 【问题描述】:

我想将某些文件类型(例如“.txt”)与不以特定子字符串结尾的非空根名称(例如“-bad”)进行匹配。有了负面的后向支持,解决方案很简单:

/.(?<!-bad)\.txt$/

Safari,然而,仍然不支持负面的后视。啊。我怎样才能使用负前瞻来获得相同的结果?我想用一个正则表达式来做到这一点。请不要提供任何非正则表达式或多步解决方案。

下面的测试代码表明我已经接近了,但一项测试仍然失败。 ????

const regex = /.((?!-bad).4)\.txt$/;
const tests = [
  ['this-file-bad.txt', false],
  ['this-file.txt', true],
  ['.txt', false],
  ['f.txt', true]
];

const results = tests.map(([input, expected]) => ((regex.test(input) === expected) ? '✅' : '❌') + input);
console.log(results.join('\n'));

【问题讨论】:

【参考方案1】:

你可以使用

^(?!.*\-bad\.txt$).+\.txt$

Demo1

正则表达式如下:

匹配字符串的开头 (^) 使用否定前瞻 ((?!...)) 断言字符串不以“-bad.txt”结尾 匹配一个或多个字符,后跟字符串末尾的“.txt”。

要同时检查多个文件中的任何一个(根据您下面的评论,这可能会有所帮助),您可以编写,例如:

^(?=.*\.(txt|pdf|csv|docx|html|jpeg)$)(?!.*\-bad\.\1$).+\.\1$

开头的肯定前瞻的唯一目的是捕获字符串末尾的文件后缀,以便可以在否定前瞻和结尾处使用反向引用。

Demo2

【讨论】:

感谢@MikeM 指出我犯的两个粗心错误。 酷。我对这个解决方案的唯一担心是扩展提供了两次。由于我在实际应用程序中匹配的不仅仅是“txt”,这意味着在表达式中复制大量扩展名。有什么办法可以避免重复扩展? :) 如果没有,我可能不得不保留@MikeM 的原始解决方案。希望他没有删除它,呵呵。 恶魔,如果没记错的话,@MikeM 的正则表达式是^(?:.1,3|.*(?!-bad)....)\.txt$。你可能认为我记性很好。具有特定代表的成员会知道其他情况。 恶魔,希望你今晚能睡个好觉。

以上是关于如何使用负前瞻(NOT lookbehind)来匹配在特定位置不包含给定子字符串的字符串?的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式忽略分组顺序匹配(前瞻后顾负前瞻负后顾的应用)

正则表达式前瞻(?=)后顾(?<)负前缀(?!)负后顾(?<!)

负前瞻正则表达式贪婪(为啥.*?太贪婪)

负前瞻行为不符合预期

Prometheus(公制)使用逆正则表达式匹配/负前瞻重新标记配置

负前瞻正则表达式