我正在尝试对所有Ui\.
不跟随Line
字母甚至字母的情况进行grepL
编写正则表达式以查找特定字符串的所有实例(而不是其他字符串)的正确方法是什么?
提前使用
grep "Ui\.(?!L)" *
bash: !L: event not found
grep "Ui\.(?!(Line))" *
nothing
set +o histexpand
在Bash或set +H
YMMV中。
我正在尝试对所有Ui\.
不跟随Line
字母甚至字母的情况进行grepL
编写正则表达式以查找特定字符串的所有实例(而不是其他字符串)的正确方法是什么?
提前使用
grep "Ui\.(?!L)" *
bash: !L: event not found
grep "Ui\.(?!(Line))" *
nothing
set +o histexpand
在Bash或set +H
YMMV中。
Answers:
负向超前,这就是您所追求的,它需要比standard更为强大的工具grep
。您需要启用了PCRE的grep。
如果您具有GNU grep
,则当前版本支持options -P
或--perl-regexp
,然后可以使用所需的正则表达式。
如果您没有GNU(最新版本)grep
,请考虑获取ack
。
!
视为特殊字符。
-P
不支持的那些,请再次尝试将结果管道输送到grep --invert-match
,例如:git log --diff-filter=D --summary | grep -E 'delete.*? src' | grep -E --invert-match 'xml'
。确保支持@Vinicius Ottoni的答案。
部分问题的答案在这里,而ack的行为方式相同: Ack和否定超前提示错误
您正在对grep使用双引号,这使bash可以“解释!
为历史记录扩展命令”。
您需要将模式包装在SINGLE-QUOTES中:
grep 'Ui\.(?!L)' *
但是,请参阅@JonathanLeffler的答案,以解决标准中的负先行问题grep
!
grep
与standard的功能混为一谈grep
,其中的标准grep
是POSIX。您所说的也是正确的-我在禁用C-shell野蛮行为的情况下运行Bash(因为如果我想要一个C shell,我会使用一个,但是我不想要一个),所以这些!
内容不会影响我-但是要获得负面的反感,您需要使用非标准grep
。
您可能无法使用grep执行标准的否定先行,但通常您应该能够使用“反向”开关'-v'获得同等的行为。使用它,您可以为要匹配的内容构造一个正则表达式,然后将其通过2个粗线传送。
对于正则表达式,您可能会做类似的事情
grep 'Ui\.' * | grep -v 'Ui\.L'
如果您需要使用不支持否定先行的正则表达式实现,并且不介意匹配额外的字符*,则可以使用否定的字符类[^L]
,替换|
和字符串锚定结尾$
。
在您的情况下,grep 'Ui\.\([^L]\|$\)' *
就可以了。
Ui\.
匹配您感兴趣的字符串
\([^L]\|$\)
匹配除以外的任何单个字符,L
或者匹配行的末尾:[^L]
或$
。
如果要排除多个字符,则只需要对它进行更多的替换和否定即可。查找后a
不跟bc
:
grep 'a\(\([^b]\|$\)\|\(b\([^c]\|$\)\)\)' *
其是(a
接着通过不b
或随后行的末尾:a
然后[^b]
或$
)或(a
随后b
其或者随后不c
或之后是该线的端部:a
然后b
,然后[^c]
或$
。
即使很短的字符串,这种表达也很笨拙并且容易出错。您可以编写一些内容来为您生成表达式,但是仅使用支持否定先行的正则表达式实现可能会更容易。
*如果您的实现支持非捕获组,则可以避免捕获额外的字符。
如果您的grep不支持-P或--perl-regexp,并且您可以安装启用PCRE的grep(例如“ pcregrep”),则它将不需要任何命令行选项(例如GNU grep)来接受与Perl兼容的常规表达式,您只需运行
pcregrep "Ui\.(?!Line)"
您不需要在示例“ Ui。(?!(Line))”中为“ Line”添加另一个嵌套组-外部组就足够了,就像我上面显示的那样。
让我给您看一个看似否定断言的另一个示例:当您有由“ ipset”返回的行列表时,每行显示该行中间的数据包数量,而您不需要零数据包的行,您只需跑:
ipset list | pcregrep "packets(?! 0 )"
如果您喜欢与perl兼容的正则表达式并且具有perl但没有pcregrep或您的grep不支持--perl-regexp,则可以单行运行与grep相同的方式的perl脚本:
perl -e "while (<>) {if (/Ui\.(?!Lines)/){print;};}"
Perl像grep一样接受stdin,例如
ipset list | perl -e "while (<>) {if (/packets(?! 0 )/){print;};}"