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

入口:

hoho
hihi
haha
hede

代码:

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

所需的产量:

hoho
hihi
haha

当前回答

此前提到的(?(?!)*是很棒的,因为它可以被 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

其他回答

如果您希望 regex 测试只会失败,如果整个序列相匹配,则下列内容将工作:

^(?!hede$).*

例如 - 如果你想允许除了“foo”以外的所有值(即“foofoo”,“barfoo”和“foobar”将通过,但“foo”将失败),请使用: ^(?!foo$)。

当然,如果你正在检查准确的平等,在这种情况下,一个更好的总体解决方案是检查序列平等,也就是说。

myStr !== 'foo'

您甚至可以将拒绝置于测试之外,如果您需要任何 regex 功能(这里,案例不敏感性和范围匹配):

!/^[a-f]oo$/i.test(myStr)

但是,这个答案的顶部的 regex 解决方案在需要积极的 regex 测试的情况下可能有用(可能是通过 API)。

这就是我这样做的方式:

^[^h]*(h(?!ede)[^h]*)*$

比其他答案更准确、更有效,它实施了弗里德尔的“无滚动”效率技术,需要更少的后续追踪。

不是雷格斯,但我发现使用带管的序列粘贴是合乎逻辑和有用的,以消除噪音。

例如,搜索一个 Apache 配置文件,没有所有评论 -

grep -v '\#' /opt/lampp/etc/httpd.conf      # this gives all the non-comment lines

grep -v '\#' /opt/lampp/etc/httpd.conf |  grep -i dir

序列格雷普的逻辑是(不是一个评论)和(比赛是)

^((?!hede).) *$ 是一个优雅的解决方案,除非它消耗字符,你将无法将其与其他标准相结合。 例如,说你想检查“hede”的不存在和“haha”的存在。

^(?!.*\bhede\b)(?=.*\bhaha\b) 

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

原因在于,没有旗帜,POSIX接口只需要使用基本常规表达式(BRE),这些表达式只是不足以完成这个任务,因为缺乏替代的子表达式。

grep "^\([^h]\|h\(h\|eh\|edh\)*\([^eh]\|e[^dh]\|ed[^eh]\)\)*\(\|h\(h\|eh\|edh\)*\(\|e\|ed\)\)$" input

(与格雷尔和一些额外的优化手工完成)。

egrep "^([^h]|h(h|eh|edh)*([^eh]|e[^dh]|ed[^eh]))*(|h(h|eh|edh)*(|e|ed))$" input

#!/bin/bash
REGEX="^\([^h]\|h\(h\|eh\|edh\)*\([^eh]\|e[^dh]\|ed[^eh]\)\)*\(\|h\(h\|eh\|edh\)*\(\|e\|ed\)\)$"

# First four lines as in OP's testcase.
cat > testinput.txt <<EOF
hoho
hihi
haha
hede

h
he
ah
head
ahead
ahed
aheda
ahede
hhede
hehede
hedhede
hehehehehehedehehe
hedecidedthat
EOF
diff -s -u <(grep -v hede testinput.txt) <(grep "$REGEX" testinput.txt)

Files /dev/fd/63 and /dev/fd/62 are identical

如预期。

对于那些对细节感兴趣的人来说,使用的技术是将与词相匹配的常规表达式转换为终端自动,然后转换自动,将每个接受状态转换为不接受,反之亦然,然后将结果的FA转换为常规表达式。

grep -P '^((?!hede).)*$' input

^([^h]|h(h|e(h|dh))*([^eh]|e([^dh]|d[^eh])))*(h(h|e(h|dh))*(ed?)?)?$