2014-08-31 58 views
1

我正在尝试搜索包含'foo'的行,但这些行不得包含'bar'。用ack这些参数进行搜索的好方法是什么?如何用ack指定忽略模式?

我可以这样做:

ack "foo" | grep -v "bar"

,但它不保存ack的漂亮叠合了和彩色输出。此外,与ack不同,grep不支持Perl正则表达式。

+0

@TomFenech是的,非常抱歉。我在发布问题后出于某种原因纠正了几分钟,但没有持续。 – DBedrenko 2014-08-31 09:48:21

+0

你不能使用'awk'?它会轻松做到这一点。 – Jotne 2014-08-31 10:12:57

+0

@Jotne'ack'更适合搜索文本文件,特别是源代码,并且有很多适合这个特性的特性,使它成为比awk更好的工具。例如'awk'只支持POSIX ERE,这对我来说是一种破坏行为;另一方面,'ack'支持Perl正则表达式。 – DBedrenko 2014-08-31 10:18:26

回答

4

您可以使用一个稍微复杂的正则表达式:

ack '^(?!.*bar).*(foo)' file 

(?!...)做了负前瞻,以确保“吧”是不是就行了。以下是它的工作方式:

  • ^从行首开始。
  • (?!.*bar)前进任意数量的字符,直到找到“bar”。如果发现,请不要继续。否则,返回到行首并继续。
  • .*(foo)匹配(和捕捉)“foo”在行的开始和结束之间的任何点。

测试出来:

$ cat file 
other foo bar 
baz foo other 
$ ack '^(?!.*bar).*(foo)' file 
baz foo other 
+0

与@ jcl的答案不同的建议不同,这只突出搜索词而不是整行。我可以尝试用某种方法制作一个'ack'包装,这样我就不必输入那么长的正则表达式。谢谢! – DBedrenko 2014-08-31 10:13:44

+1

没问题。只有单词被突出显示的原因是因为我已经将它包含在捕获组“(foo)”中。如果删除括号,则整行将突出显示。 – 2014-08-31 10:16:54

+0

请你能解释为什么带有“酒吧”的线条会被忽略,即使它们的位置在“foo”之后?我认为,后面看起来*匹配模式。 – DBedrenko 2014-08-31 10:29:58

4

一种可能性是使用ack本身的排斥通,并扭转调用的顺序:

ack -v "bar" | ack "foo" 

至少会突出搜索词,但它不会让你完全一样格式化只是ack "foo"

另一种可能是在同一个正则表达式的两项打包在一起,使用负前瞻的排除项,因为在这个答案给出:

Multiple patterns with ack-grep?

ack '^(?!.*bar).*foo.*$' 

,将让你ack的每个文件格式,但整行将突出显示为搜索项。