How to match once per file in grep?

后端 未结 6 1097
再見小時候
再見小時候 2021-02-06 20:38

Is there any grep option that let\'s me control total number of matches but stops at first match on each file?

Example:

If I do this grep -ri --include \'*

相关标签:
6条回答
  • 2021-02-06 20:54

    I would do this in awk instead.

    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 '/re/ {print FILENAME ":" $0;nextfile}' *.coffee
    

    Or, if you're using a current enough bash, you can use globstar:

    shopt -s globstar
    awk '/re/ {print FILENAME ":" $0;nextfile}' **/*.coffee
    
    0 讨论(0)
  • 2021-02-06 21:02

    using find and xargs. find every .coffee files and excute -m1 grep to each of them

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

    test without -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

    linux# find . -name '*.txt'|xargs grep -m1 -ri 'oyss'
    ./test1.txt:oyss
    ./test2.txt:oyss1
    
    0 讨论(0)
  • 2021-02-06 21:03

    You can do this easily in perl, and no messy cross platform issues!

    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. They're not much different.

    You can do the recursive part in Perl using File::Find, or use find feed it files.

    find /some/path -name '*.coffee' -print0 | xargs -0 perl /path/to/your/program
    
    0 讨论(0)
  • 2021-02-06 21:09

    I think you can just do something like

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

    to e.g. 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; GNU grep does do this, but BSD grep apparently treats it as a global match limit.

    0 讨论(0)
  • 2021-02-06 21:09

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

    find's -exec option runs the command once for each matched file (unless you use + instead of \;, which makes it act like xargs).

    0 讨论(0)
  • 2021-02-06 21:14

    So, using grep, you just need the option -l, --files-with-matches.

    All those answers about find, awk or shell scripts are away from the question.

    0 讨论(0)
提交回复
热议问题