我知道可以匹配一个单词,然后用其他工具逆转比赛(例如 grep -v)。但是,可以匹配不包含一个特定的单词,例如 hede,使用常规表达式的线条吗?
入口:
hoho
hihi
haha
hede
代码:
grep "<Regex for 'doesn't contain hede'>" input
所需的产量:
hoho
hihi
haha
我知道可以匹配一个单词,然后用其他工具逆转比赛(例如 grep -v)。但是,可以匹配不包含一个特定的单词,例如 hede,使用常规表达式的线条吗?
入口:
hoho
hihi
haha
hede
代码:
grep "<Regex for 'doesn't contain hede'>" input
所需的产量:
hoho
hihi
haha
当前回答
如何使用PCRE的背景跟踪控制字符,以匹配一行不包含单词
下面是我以前从未使用过的一种方法:
/.*hede(*COMMIT)^|/
它是如何工作的
首先,它试图在线上的某个地方找到“故障”。如果成功,在这一点上,(COMMIT)告诉发动机,不只是在故障的情况下不落后,而且也不会试图在这种情况下进一步匹配。
如果一行不包含“干”则第二个替代品,一个空的子模式,成功地匹配主题行。
这个方法不比一个负面看法更有效,但我想我只是把它扔在这里,如果有人发现它是零,并找到一个用于其他,更有趣的应用程序。
其他回答
请注意,解决方案不会从“现在”开始:
^(?!hede).*$
一般来说,它比解决方案不包含“这些”的更有效:
^((?!hede).)*$
前者只在输入行的第一个位置检查“点”而不是每个位置。
此前提到的(?(?!)*是很棒的,因为它可以被 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
使用 ConyEdit,您可以使用命令行 cc.gl!/hede/ 获取不包含 regex 匹配的行,或者使用命令行 cc.dl /hede/ 删除包含 regex 匹配的行。
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
雷格克斯的拒绝本身并不特别有用,但当你也有交叉时,事情变得有趣,因为你有一个完整的布莱恩组操作:你可以表达“与此相匹配的组,除了与此相匹配的东西”。
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?)?)?$