Grep只有第一场比赛并停止

Tim*_*amm 287 grep

我正在使用grep使用以下参数递归搜索目录,希望只返回第一个匹配项.不幸的是,它返回了不止一个 - 实际上是我最后一次看的两个.看起来我有太多的争论,特别是没有得到预期的结果.: - /

# grep -o -a -m 1 -h -r "Pulsanti Operietur" /path/to/directory
Run Code Online (Sandbox Code Playgroud)

收益:

Pulsanti Operietur
Pulsanti Operietur
Run Code Online (Sandbox Code Playgroud)

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

mvp*_*mvp 455

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

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

grep -o -a -m 1 -h -r "Pulsanti Operietur" /path/to/dir | head -1
Run Code Online (Sandbox Code Playgroud)

  • @Chris_Rands确切的行为取决于你正在运行的shell.头会在遇到第一行时立即退出.grep将在下一次磁头退出后尝试写入时退出.有些shell会等到管道的所有元素都完成,有些会在管道中的最后一个程序退出时导致整个管道关闭. (5认同)
  • 正是我需要的.我的模式在同一行上被发现两次,并且`grep -m 1`因为这个原因返回了两个实例.`| head -1`解决了! (3认同)
  • 一旦找到第一个匹配项,“head”会短路吗? (3认同)
  • 我不认为它们是必要的(显然除了`-r`),但它们不应该受伤(我不会使用`-a`) (2认同)
  • 谢谢!这应该标记为答案! (2认同)
  • @3Qn,我不明白你的评论:“首先不是结果中的第一个”。此答案打印任何文件中的第一个匹配项并停止。你还期待什么? (2认同)

Kat*_*ers 36

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

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

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

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

-m num, --max-count=num
        Stop reading the file after num matches.
Run Code Online (Sandbox Code Playgroud)

更长的解释

就我而言,我试图仅获取相对路径的第一部分(some在下面的示例中):

-m num, --max-count=num
        Stop reading the file after num matches.
Run Code Online (Sandbox Code Playgroud)

当它返回给我时我很困惑

some
path
here
Run Code Online (Sandbox Code Playgroud)

感谢上面@harperville的评论,我终于弄清楚:这不是关于输出而是关于输入

确实,当我尝试时

> echo "some/path/here" | grep -E -o -m 1 '[^\/]+'
Run Code Online (Sandbox Code Playgroud)

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

笔记

对于那些不太熟悉的人grep

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


Ven*_*tra 29

您可以将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
Run Code Online (Sandbox Code Playgroud)

只要head消耗1线,它终止,grep会收到SIGPIPE因为它仍然输出的东西管而head消失了.

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

  • `grep` 的 `--line-buffered` 选项不会在不调用其他实用程序的情况下防止缓冲区开销吗? (3认同)

And*_*ter 21

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

  • 我已经使用Ack了很长一段时间,但最近切换到[银色搜索者](https://github.com/ggreer/the_silver_searcher)我发现Ack更快 (2认同)

小智 12

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

grep -m 1 -r "Not caching" * | head -1
Run Code Online (Sandbox Code Playgroud)


Ser*_*reu 6

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

$ ifconfig | grep -E -o -m 1 "^[a-z0-9]+"
Run Code Online (Sandbox Code Playgroud)

说明:
-E 表示扩展正则表达式,
-o 只返回匹配本身,
-m 1 只查找一个匹配