如何在grep中匹配每个文件一次?

pat*_*rit 48 regex unix shell perl grep

是否有任何grep选项让我控制匹配的总数但在每个文件的第一次匹配时停止?

例:

如果我这样做,grep -ri --include '*.coffee' 're' .我得到这个:

./app.coffee:express = require 'express'
./app.coffee:passport = require 'passport'
./app.coffee:BrowserIDStrategy = require('passport-browserid').Strategy
./app.coffee:app = express()
./config.coffee:    session_secret: 'nyan cat'
Run Code Online (Sandbox Code Playgroud)

如果我这样做grep -ri -m2 --include '*.coffee' 're' .,我会得到这个:

./app.coffee:config = require './config'
./app.coffee:passport = require 'passport'
Run Code Online (Sandbox Code Playgroud)

但是,我真正想要的是这个输出:

./app.coffee:express = require 'express'
./config.coffee:    session_secret: 'nyan cat'
Run Code Online (Sandbox Code Playgroud)

-m1不起作用,因为我得到这个grep -ri -m1 --include '*.coffee' 're' .

./app.coffee:express = require 'express'
Run Code Online (Sandbox Code Playgroud)

尝试不使用grep,例如这find . -name '*.coffee' -exec awk '/re/ {print;exit}' {} \;产生:

config = require './config'
    session_secret: 'nyan cat'
Run Code Online (Sandbox Code Playgroud)

更新:如下所述,GNU grep -m选项处理每个文件的计数,而-mBSD grep将其视为全局匹配计数

fen*_*llp 44

所以,使用grep,你只需要选项-l, --files-with-matches.

所有这些有关答复find,awk或shell脚本是从问题了.

  • 这正是我所寻找的,绝对是这个问题的最佳答案!谢谢 :) (2认同)

nne*_*neo 35

我想你可以做点什么

grep -ri -m1 --include '*.coffee' 're' . | head -n 2
Run Code Online (Sandbox Code Playgroud)

例如,从每个文件中选择第一个匹配,并且最多选择两个匹配.

请注意,这需要您grep将其-m视为每个文件的匹配限制; GNU grep确实这样做,但BSD grep显然将其视为全局匹配限制.

  • 我可以确认,OS X 10.8.2上的/ usr/bin/grep是`(BSD grep)2.5.1-FreeBSD`,它的`-m`是全局的,而不是每个文件.GNU grep是每个文件.nneonneo,你必须用GNU工具覆盖`/ usr/bin`.@wrick我建议使用GNU工具,OS X附带的BSD工具有点笨拙.从长远来看,它将使您的生活更轻松.使用[MacPorts](http://www.macports.org/)或[homebrew](http://mxcl.github.com/homebrew/). (4认同)
  • -m1在我的全球比赛中停止。无论如何,如果有数百万个匹配项,而我只想要其中的100个匹配项,那么这效率低下,因为grep在将结果传递到“ head”之前仍会进行前一百万个匹配项 (2认同)
  • 我从来没有听说过-m在全局范围内而不是每个文件中起作用。如果这在OSX 10.8中发生,那是一种Apple主义,与FreeBSD的GNU grep端口无关。(请注意,如果确实有“ BSD grep”之类的东西;它不是来自FreeBSD。FreeBSD仍然使用GNU grep 2.5.1的端口,因为它(和OSX)已经使用了多年。) (2认同)

gho*_*oti 5

我会这样做awk.

find . -name \*.coffee -exec awk '/re/ {print FILENAME ":" $0;exit}' {} \;
Run Code Online (Sandbox Code Playgroud)

如果你不需要递归,你可以用awk来做:

awk '/re/ {print FILENAME ":" $0;nextfile}' *.coffee
Run Code Online (Sandbox Code Playgroud)

或者,如果你使用足够的当前bash,你可以使用globstar:

shopt -s globstar
awk '/re/ {print FILENAME ":" $0;nextfile}' **/*.coffee
Run Code Online (Sandbox Code Playgroud)