简体   繁体   English

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

[英]How to match once per file in grep?

Is there any grep option that let's me control total number of matches but stops at first match on each file? 是否有任何grep选项让我控制匹配的总数但在每个文件的第一次匹配时停止?

Example: 例:

If I do this grep -ri --include '*.coffee' 're' . 如果我这样做grep -ri --include '*.coffee' 're' . I get this: 我明白了:

./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'

And if I do grep -ri -m2 --include '*.coffee' 're' . 如果我做grep -ri -m2 --include '*.coffee' 're' . , I get this: ,我明白了:

./app.coffee:config = require './config'
./app.coffee:passport = require 'passport'

But, what I really want is this output: 但是,我真正想要的是这个输出:

./app.coffee:express = require 'express'
./config.coffee:    session_secret: 'nyan cat'

Doing -m1 does not work as I get this for grep -ri -m1 --include '*.coffee' 're' . -m1不起作用,因为我得到这个grep -ri -m1 --include '*.coffee' 're' .

./app.coffee:express = require 'express'

Tried not using grep eg this find . -name '*.coffee' -exec awk '/re/ {print;exit}' {} \\; 尝试不使用grep例如这个find . -name '*.coffee' -exec awk '/re/ {print;exit}' {} \\; find . -name '*.coffee' -exec awk '/re/ {print;exit}' {} \\; produced: 制作:

config = require './config'
    session_secret: 'nyan cat'

UPDATE: As noted below the GNU grep -m option treats counts per file whereas -m for BSD grep treats it as global match count 更新:如下所述,GNU grep -m选项处理每个文件的计数,而-m表示BSD grep将其视为全局匹配计数

So, using grep , you just need the option -l, --files-with-matches . 因此,使用grep ,您只需要选项-l, --files-with-matches

All those answers about find , awk or shell scripts are away from the question. 关于findawk或shell脚本的所有答案都远离问题。

I think you can just do something like 我想你可以做点什么

grep -ri -m1 --include '*.coffee' 're' . | head -n 2

to eg pick the first match from each file, and pick at most two matches total. 例如,从每个文件中选择第一个匹配,并且最多选择两个匹配。

Note that this requires your grep to treat -m as a per-file match limit; 请注意,这需要您的grep-m视为每个文件的匹配限制; GNU grep does do this, but BSD grep apparently treats it as a global match limit. GNU grep会这样做,但BSD grep显然将其视为全局匹配限制。

I would do this in awk instead. 我会用awk来做这件事。

find . -name \*.coffee -exec awk '/re/ {print FILENAME ":" $0;exit}' {} \;

If you didn't need to recurse, you could just do it with awk: 如果你不需要递归,你可以用awk来做:

awk '/re/ {print FILENAME ":" $0;nextfile}' *.coffee

Or, if you're using a current enough bash, you can use globstar: 或者,如果你使用足够的当前bash,你可以使用globstar:

shopt -s globstar
awk '/re/ {print FILENAME ":" $0;nextfile}' **/*.coffee

using find and xargs. 使用find和xargs。 find every .coffee files and excute -m1 grep to each of them 找到每个.coffee文件并为每个文件执行excute -m1 grep

find . -print0 -name '*.coffee'|xargs -0 grep -m1 -ri 're'

test without -m1 没有-m1的测试

linux# find . -name '*.txt'|xargs grep -ri 'oyss'
./test1.txt:oyss
./test1.txt:oyss1
./test1.txt:oyss2
./test2.txt:oyss1
./test2.txt:oyss2
./test2.txt:oyss3

add -m1 添加-m1

linux# find . -name '*.txt'|xargs grep -m1 -ri 'oyss'
./test1.txt:oyss
./test2.txt:oyss1

find . -name \\*.coffee -exec grep -m1 -i 're' {} \\;

find的-exec选项为每个匹配的文件运行一次命令(除非你使用+而不是\\; ;,这使它像xargs一样)。

You can do this easily in perl, and no messy cross platform issues! 你可以在perl中轻松完成这个任务,而且不会出现凌乱的跨平台问题!

use strict;
use warnings;
use autodie;

my $match = shift;

# Compile the match so it will run faster
my $match_re = qr{$match};

FILES: for my $file (@ARGV) {
    open my $fh, "<", $file;

    FILE: while(my $line = <$fh>) {
        chomp $line;

        if( $line =~ $match_re ) {
            print "$file: $line\n";
            last FILE;
        }
    }
}

The only difference is you have to use Perl style regular expressions instead of GNU style. 唯一的区别是你必须使用Perl样式的正则表达式而不是GNU样式。 They're not much different . 他们并没有太大的不同

You can do the recursive part in Perl using File::Find , or use find feed it files. 您可以使用File :: Find在Perl中执行递归部分,或使用find feed it files。

find /some/path -name '*.coffee' -print0 | xargs -0 perl /path/to/your/program

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM