我正在使用带有以下参数的 grep 递归搜索目录,希望只返回第一个匹配项。不幸的是,它返回的不止一个——实际上是我上次查看时返回的两个。似乎我有太多的争论,尤其是没有得到想要的结果。 :-/
# grep -o -a -m 1 -h -r "Pulsanti Operietur" /path/to/directory
返回:
Pulsanti Operietur
Pulsanti Operietur
也许 grep 不是最好的方法?你告诉我,非常感谢。
-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
您可以将 grep
结果与 stdbuf 一起通过管道传输到 head
。
请注意,为了确保在第 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
消失时它仍然输出一些东西到管道。
这假设没有文件名包含换行符。
xargs
: find . -name '*.gz' | xargs -I '{}' stdbuf -oL zgrep -al 'pattern' {} | head -n 1
的大量存档文件。但是,这不会在第一场比赛中终止。有什么建议吗?
grep
的 --line-buffered
选项不会在不调用其他实用程序的情况下防止缓冲区开销吗?
我的 grep-a-like 程序 ack
有一个 -1
选项,它会在任何地方找到第一个匹配项时停止。它也支持@mvp 所指的-m 1
。我把它放在那里是因为如果我正在搜索一棵大树的源代码来找到我知道只存在于一个文件中的东西,那么没有必要找到它并且必须按 Ctrl-C。
ag
可能很快,但它没有具有在这种情况下有用的 -1
选项
如果要在当前目录中出现特定单词时要打印整行和文件名,则可以使用以下命令。
grep -m 1 -r "Not caching" * | head -1
对于像我一样登陆这里的任何人,对于为什么 --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.
更长的解释
就我而言,我试图仅获取相对路径的第一部分:
> 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 因为我从来没有这样考虑一下。 (专业提示:将别名 grep="grep -E" 添加到您的 .zshrc 中,您将永远不必再担心它!)
-o (--only-matching) 告诉它只打印匹配项,而不是找到匹配项的每一行。
-mn (--max-count n) 将其限制为搜索 n 行。 (如果你读到这里,你显然已经知道了!😛)
阅读 grep 手册(man grep),这是查找与扩展正则表达式的第一个匹配项的最少命令。获取我笔记本电脑中的以太网名称不是 eth0 的示例!
$ ifconfing | grep -E -o -m 1 "^[a-z0-9]+"
说明:-E 表示扩展正则表达式,-o 只返回匹配项,-m 1 只看一行
单个衬里,使用 find
:
find -type f -exec grep -lm1 "PATTERN" {} \; -a -quit
grep -r
的工作速度要快得多 - 它只有一个副本可以进行目录遍历。
-r
除外),但它们不应该受到伤害(虽然我不会使用-a
)grep -m 1
返回了两个实例。|head -1
解决了!head
是否会短路?first not first from result
。此答案在任何文件中打印第一个匹配项并停止。你还期待什么?