我知道可以匹配一个单词,然后用其他工具逆转比赛(例如 grep -v)。但是,可以匹配不包含一个特定的单词,例如 hede,使用常规表达式的线条吗?

入口:

hoho
hihi
haha
hede

代码:

grep "<Regex for 'doesn't contain hede'>" input

所需的产量:

hoho
hihi
haha

当前回答

请注意,解决方案不会从“现在”开始:

^(?!hede).*$

一般来说,它比解决方案不包含“这些”的更有效:

^((?!hede).)*$

前者只在输入行的第一个位置检查“点”而不是每个位置。

其他回答

答案非常好,只是一个学术点:

计算机科学的理论意义上的常规表达是不可能这样做的,对他们来说,它应该看起来像这样:

^([^h].*$)|(h([^e].*$|$))|(he([^h].*$|$))|(heh([^e].*$|$))|(hehe.+$) 

这只是一场完整的比赛,做下一场比赛会更可怕。

此前提到的(?(?!)*是很棒的,因为它可以被 anchored。

^(?:(?!hede).)*$               # A line without hede

foo(?:(?!hede).)*bar           # foo followed by bar, without hede between them

但在这种情况下,以下几点就足够了:

^(?!.*hede)                    # A line without hede

此简化已准备好添加“和”条款:

^(?!.*hede)(?=.*foo)(?=.*bar)   # A line with foo and bar, but without hede
^(?!.*hede)(?=.*foo).*bar       # Same

请注意,解决方案不会从“现在”开始:

^(?!hede).*$

一般来说,它比解决方案不包含“这些”的更有效:

^((?!hede).)*$

前者只在输入行的第一个位置检查“点”而不是每个位置。

TXR 语言支持 regex 拒绝。

$ txr -c '@(repeat)
@{nothede /~hede/}
@(do (put-line nothede))
@(end)'  Input

一个更复杂的例子:匹配所有从 a 开始和 z 结束的线条,但不包含底层的线条:

$ txr -c '@(repeat)
@{nothede /a.*z&~.*hede.*/}
@(do (put-line nothede))
@(end)' -
az         <- echoed
az
abcz       <- echoed
abcz
abhederz   <- not echoed; contains hede
ahedez     <- not echoed; contains hede
ace        <- not echoed; does not end in z
ahedz      <- echoed
ahedz

雷格克斯的拒绝本身并不特别有用,但当你也有交叉时,事情变得有趣,因为你有一个完整的布莱恩组操作:你可以表达“与此相匹配的组,除了与此相匹配的东西”。

# 一个简单的方式
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