66

一致の総数を制御できるが、各ファイルの最初の一致で停止する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'

そして、私がそうするならgrep -ri -m2 --include '*.coffee' 're' .、私はこれを手に入れます:

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

しかし、私が本当に欲しいのはこの出力です:

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

-m1はこれを取得するので、実行は機能しませんgrep -ri -m1 --include '*.coffee' 're' .

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

grepを使用しないようにしました。例:これは次のようにfind . -name '*.coffee' -exec awk '/re/ {print;exit}' {} \;生成されます。

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

更新:以下に示すように、GNU grep-mオプションはファイルごとのカウントを扱いますが-m、BSDの場合はgrepはそれをグローバル一致カウントとして扱います

4

6 に答える 6

79

したがって、を使用grepすると、オプションが必要になります-l, --files-with-matches

find、またはシェルスクリプトに関するこれらの回答はすべてawk、質問から離れています。

于 2014-03-25T10:50:27.747 に答える
42

私はあなたがただのようなことをすることができると思います

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

たとえば、各ファイルから最初の一致を選択し、合計で最大2つの一致を選択します。

これには、ファイルごとの一致制限としてgrep扱う必要があることに注意してください。-mGNUgrepはこれを行いますが、BSDgrepは明らかにそれをグローバルな一致制限として扱います。

于 2012-10-11T02:53:37.227 に答える
4

代わりにこれを行いawkます。

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

再帰する必要がない場合は、awkでそれを行うことができます。

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

または、現在十分な数のbashを使用している場合は、globstarを使用できます。

shopt -s globstar
awk '/re/ {print FILENAME ":" $0;nextfile}' **/*.coffee
于 2012-10-11T03:11:22.383 に答える
2

findとxargsを使用します。すべての.coffeeファイルを検索し、それぞれに-m1grepを実行します

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

-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

-m1を追加

linux# find . -name '*.txt'|xargs grep -m1 -ri 'oyss'
./test1.txt:oyss
./test2.txt:oyss1
于 2012-10-11T03:38:57.670 に答える
2

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

findの-execオプションは、一致したファイルごとにコマンドを1回実行します(+の代わりにを使用すると\;、xargsのように機能します)。

于 2012-10-11T04:56:17.507 に答える
0

これは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;
        }
    }
}

唯一の違いは、GNUスタイルの代わりにPerlスタイルの正規表現を使用する必要があることです。 それらはそれほど違いはありません

File :: Findを使用してPerlで再帰的な部分を実行するか、ファイルをfindフィードすることを使用できます。

find /some/path -name '*.coffee' -print0 | xargs -0 perl /path/to/your/program
于 2012-10-11T03:37:34.813 に答える