正则表达式用于匹配不包含某个单词的行

5321

我知道可以使用其他工具(例如 grep -v)来匹配一个词并反转匹配结果。然而,是否可能使用正则表达式来匹配不包含特定单词(例如 hede)的行?

输入:
hoho
hihi
haha
hede
代码:
grep "<Regex for 'doesn't contain hede'>" input
期望的输出:
hoho
hihi
haha

105
也许有几年的延迟,但是这个正则表达式 ([^h]*(h([^e]|$)|he([^d]|$)|hed([^e]|$)))* 有什么问题吗?它的思想很简单。继续匹配直到看到不想要的字符串的开头,然后只在字符串未完成的N-1种情况下进行匹配(其中N为字符串的长度)。这N-1种情况是“h之后非e”,“he之后非d”和“hed之后非e”。如果你成功通过了这些N-1种情况,那么你就成功地没有匹配上不想要的字符串,所以你可以开始再次寻找[^h]* - stevendesu
430
尝试输入“a-very-very-long-word”或更好的方式是半个句子。打字愉快。顺便说一句,这几乎无法阅读。不清楚性能影响如何。 - Peter Schuetze
14
@PeterSchuetze:当然,对于非常长的单词来说,这种方法可能不太美观,但它是可行且正确的解决方案。虽然我没有测试过其性能,但我认为它不会太慢,因为大多数后面的规则都被忽略了,直到你看到一个h(或单词、句子等的第一个字母)。而且你可以很容易地使用迭代连接生成长字符串的正则表达式字符串。如果它有效且能够快速生成,那么可读性重要吗?对此可以在评论中进行说明。 - stevendesu
66
@stevendesu: 我来晚了,但是那个答案几乎完全错误。首先,它要求主题包含“h”,而实际上不应该要求,因为任务是“匹配不包含特定单词的行”。我们假设你的意思是使内部组变为可选的,并且该模式已经被锚定:^([^h]*(h([^e]|$)|he([^d]|$)|hed([^e]|$))?)*$这个模式在 "hhede" 等包含部分"hede"的实例之前出现时失败了。 - jaytea
20
这个问题已经被添加到Stack Overflow正则表达式常见问题解答下的“高级Regex-Fu”部分。 - aliteralmind
35个回答

1

我能找到的最简单的东西就是

[^(hede)]

https://regex101.com/进行了测试。

你也可以在该网站上添加单元测试用例。


不适用于 Visual Code。 - JRichardsz
1
这段代码简单地查找了一个不是 (hed) 的单个字符。 - tripleee

1

使用ConyEdit,您可以使用命令行cc.gl !/hede/获取不包含正则表达式匹配的行,或使用命令行cc.dl /hede/删除包含正则表达式匹配的行。它们具有相同的结果。


同样地,但不那么晦涩的是,awk '!/hede/'grep -v 'hede' - tripleee

0
虽然你可以使用一个查找,但我读到一篇文章,使用了另一种方法,这种方法似乎更优雅,语法上也不那么繁琐。
这个想法有些违反直觉:实际上匹配你不想匹配的内容,但只匹配你想在组内匹配的内容,并在后面引用它们。
例如,黑名单词汇:pattern='\bTarzan\b|\bJane\b|(\w+)' 然后只需使用group(1),例如'\1',来获取不包含前缀词汇的匹配结果。
这篇文章很好地描述了这一点:https://www.rexegg.com/regex-best-trick.html#simplecase 以及这个很棒的SO回答也对其进行了描述:How do (*SKIP) or (*F) work on regex?

0
# 一个简单的方式
import re
skip_word = 'hede'
stranger_char = '虩'
content = '''hoho
hihi
haha
hede'''
print(
    '\n'.join(re.findall(
        '([^{}]*?)\n'.format(stranger_char), 
        content.replace(skip_word, stranger_char)
    )).replace(stranger_char, skip_word) 
)

# hoho
# hihi
# haha

0

使用 (?<!hede) 是更好的答案。(?<!whateverYouDontWantToMatch) 是负向零宽后顾,而不是 (?!whateverYouDontWantToMatch) 的负向零宽先行断言。这意味着通过 (?<!) 它将在字符串当前位置进行检查,而不仅仅是在匹配之后。因此例如,在使用 (?!) 时会遇到问题,它仅在此情况下起作用是因为有锚定。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接