441

我正在使用带有以下参数的 grep 递归搜索目录,希望只返回第一个匹配项。不幸的是,它返回的不止一个——实际上是我上次查看时返回的两个。似乎我有太多的争论,尤其是没有得到想要的结果。:-/

# grep -o -a -m 1 -h -r "Pulsanti Operietur" /path/to/directory

返回:

Pulsanti Operietur
Pulsanti Operietur

也许 grep 不是最好的方法?你告诉我,非常感谢。

4

7 回答 7

660

-m 1表示返回任何给定文件中的第一个匹配项。但它仍会继续在其他文件中搜索。此外,如果在同一行中有两个或更多匹配,则将显示所有这些。

你可以使用head -1来解决这个问题:

grep -o -a -m 1 -h -r "Pulsanti Operietur" /path/to/dir | head -1

每个 grep 选项的解释:

-o, --only-matching, print only the matched part of the line (instead of the entire line)
-a, --text, process a binary file as if it were text
-m 1, --max-count, stop reading a file after 1 matching line
-h, --no-filename, suppress the prefixing of file names on output
-r, --recursive, read all files under a directory recursively
于 2012-12-30T18:44:04.450 回答
45

您可以将grep结果headstdbuf结合使用。

请注意,为了确保在第 N 次匹配后停止,您需要使用stdbuf以确保grep不缓冲其输出:

stdbuf -oL grep -rl 'pattern' * | head -n1
stdbuf -oL grep -o -a -m 1 -h -r "Pulsanti Operietur" /path/to/dir | head -n1
stdbuf -oL grep -nH -m 1 -R "django.conf.urls.defaults" * | head -n1

一旦head消耗了 1 行,它就会终止并grep接收,因为它在消失SIGPIPE时仍然输出一些东西到管道。head

这假设没有文件名包含换行符。

于 2016-10-20T11:03:37.853 回答
24

我的 grep-a-like 程序ack有一个-1选项,可以在任何地方找到第一个匹配项时停止。它也支持-m 1@mvp 所指的内容。我把它放在那里是因为如果我正在搜索一棵大树的源代码以找到我知道只存在于一个文件中的东西,那么没有必要找到它并且必须按 Ctrl-C。

于 2012-12-30T18:50:27.023 回答
13

如果要在当前目录中出现特定单词时要打印整行和文件名,则可以使用以下命令。

grep -m 1 -r "Not caching" * | head -1
于 2020-01-30T05:02:33.597 回答
6

对于像我一样登陆这里的任何人,对于为什么--max-count在采取行动时似乎没有工作感到困惑stdin......

TL;DR -找到匹配项后不会--max-count n停止,它会在找到上的所有匹配项后停止。nn

(而且stdin,即使它只是一个字符串,也算作一行。)

尽管事实上,zsh 5.8至少在man grep中以这种方式描述了该选项,但这是正确的:

-m num, --max-count=num
        Stop reading the file after num matches.

更长的解释

就我而言,我试图仅获取相对路径的第一部分:

>  echo "some/path/here" | grep -E -o -m 1 '[^\/]+'

当它把我还给我的时候很困惑

some
path
here

感谢上面@harperville 的评论,我终于明白了:这不是关于输出,而是关于输入

确实,当我尝试

>  echo "some/path/here\nanother/path/there" | grep -E -o -m 1 '[^\/]+'

我得到了与上面相同的结果(即,仅\n在第二个示例中之前的部分)。

笔记

对于那些不太熟悉的人grep

  • -E( --extended-regexp) 告诉它使用“扩展的”正则表达式,即您在大多数其他编程语言中习惯使用的正则表达式。“扩展”和“基本”之间的区别并不大——只是你需要在你的正则表达式中转义哪些字符——但作为主要是 TS 和 Python 开发人员的人,我总是使用-E这种方式,因为我不需要思考关于它。(专业提示:添加alias grep="grep -E"到您的.zshrc,您将永远不必再担心它!)
  • -o( --only-matching) 告诉它只打印匹配项,而不是找到匹配项的每一行。
  • -m n( --max-count n) 将其限制为搜索n行。(如果你已经读到这里,那么你显然已经知道了!)
于 2021-11-04T01:24:34.147 回答
3

阅读 grep 手册(man grep),这是查找与扩展正则表达式的第一个匹配项的最少命令。获取我笔记本电脑中的以太网名称不是 eth0 的示例!

$ ifconfing | grep -E -o -m 1 "^[a-z0-9]+"

说明:-E 表示扩展正则表达式,-o 只返回匹配项,-m 1 只看一行

于 2021-03-08T13:22:38.917 回答
1

单个衬里,使用find

find -type f -exec grep -lm1 "PATTERN" {} \; -a -quit
于 2015-02-02T16:40:47.760 回答