Ui\.
实例,甚至只是字母L
。寻找特定字符串后面不跟随另一个字符串的正则表达式应该如何编写?
使用先行断言。
grep "Ui\.(?!L)" *
bash: !L: event not found
grep "Ui\.(?!(Line))" *
nothing
Ui\.
实例,甚至只是字母L
。grep "Ui\.(?!L)" *
bash: !L: event not found
grep "Ui\.(?!(Line))" *
nothing
如果您需要使用负向前瞻,则需要比标准的 grep
更为强大的工具,需要启用 PCRE 的 grep。
如果您拥有 GNU grep
,则当前版本支持选项-P
或--perl-regexp
,然后您可以使用所需的正则表达式。
如果您没有(足够新的版本)GNU grep
,那么可以考虑获取ack
。
!
视为特殊字符。 - NHDaly-P
选项的用户,请尝试再次将结果通过管道传递给grep --invert-match
,例如:git log --diff-filter=D --summary | grep -E 'delete.*? src' | grep -E --invert-match 'xml'
。请确保给@Vinicius Ottoni的回答点赞。 - Daniel Sokolowski你问题的一部分答案在这里,ack 的行为方式与此类似:Ack & negative lookahead giving errors
你正在使用双引号进行 grep,这允许 bash 将“!
”解释为历史扩展命令。
你需要将模式用单引号括起来:grep 'Ui\.(?!L)' *
但是,请查看@JonathanLeffler's answer以解决标准 grep
中负向前瞻的问题!
grep
的扩展功能和标准grep
的功能,其中grep
的标准是POSIX。你所说的也是正确的 - 我禁用了C-shell的野蛮行为来运行Bash(因为如果我想要一个C shell,我会使用它,但我不想要一个),所以!
这些东西对我没有影响 - 但要获得负向先行断言,你需要非标准的grep
。 - Jonathan Leffler-E
选项,它会给出 grep: repetition-operator operand invalid
的错误提示 :( - Jerry Green在grep中,您可能无法执行标准的负向后瞻,但通常可以使用“反向”开关“-v”来获得等效的行为。使用该开关,您可以构建一个用于匹配您想要排除内容的正则表达式,并将其通过两个grep进行传递。
对于所提到的正则表达式,您可以尝试像这样做:
grep 'Ui\.' * | grep -v 'Ui\.L'
(编辑:这不如真正的前瞻强,但通常可以用来解决问题。)
sed
(在 busybox/alpine 上可用)将匹配的部分替换为空,即 grep 'match.+' | sed 's/match//'
。 - lionello[^L]
、或操作|
和字符串结尾锚点$
。
在你的情况下,grep 'Ui\.\([^L]\|$\)' *
就能胜任。
Ui\.
匹配你感兴趣的字符串
\([^L]\|$\)
匹配除了L
之外的任何单个字符,或者匹配行末:[^L]
或$
。
如果你想排除多于一个字符,那么你只需要添加更多的或操作和否定即可。要查找不跟随bc
的a
:
grep 'a\(\([^b]\|$\)\|\(b\([^c]\|$\)\)\)' *
这个命令是匹配以下两种情况之一:(a
后面不是b
或者到了行尾:a
然后是[^b]
或者$
) 或者 (a
后面跟着b
,后面不是c
或者到了行尾:a
然后是b
,然后是[^c]
或者$
。
这种表达式即使是对于一个简短的字符串也会变得非常笨拙和容易出错。你可以编写一些代码来生成这些表达式,但只要使用支持负向先行断言的正则表达式实现就可能更容易些。
*如果你的实现支持非捕获组,那么你可以避免捕获额外的字符。
pcregrep "Ui\.(?!Line)"
在你的示例 "Ui.(?!(Line))" 中,你不需要另一个嵌套组来表示 "Line" -- 外部组已经足够了,就像我上面展示的那样。
让我再举一个查找否定断言的例子:当你有一个由 "ipset" 返回的行列表,每行显示中间的数据包数量,而你不需要零数据包的行时,只需运行:
ipset list | pcregrep "packets(?! 0 )"
perl -e "while (<>) {if (/Ui\.(?!Lines)/){print;};}"
Perl像grep一样接受标准输入(stdin),例如:
ipset list | perl -e "while (<>) {if (/packets(?! 0 )/){print;};}"
至少对于不想在“Ui.”之后出现“L”字符的情况,您不需要使用PCRE。
grep -E 'Ui\.($|[^L])' *
在这里,我已经确保匹配了行尾的"Ui."的特殊情况。