簡體   English   中英

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

[英]How to match once per file in 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'

如果我做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}' {} \\; find . -name '*.coffee' -exec awk '/re/ {print;exit}' {} \\; 制作:

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

更新:如下所述,GNU grep -m選項處理每個文件的計數,而-m表示BSD grep將其視為全局匹配計數

因此,使用grep ,您只需要選項-l, --files-with-matches

關於findawk或shell腳本的所有答案都遠離問題。

我想你可以做點什么

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

例如,從每個文件中選擇第一個匹配,並且最多選擇兩個匹配。

請注意,這需要您的grep-m視為每個文件的匹配限制; GNU grep會這樣做,但BSD grep顯然將其視為全局匹配限制。

我會用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

使用find和xargs。 找到每個.coffee文件並為每個文件執行excute -m1 grep

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

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

find的-exec選項為每個匹配的文件運行一次命令(除非你使用+而不是\\; ;,這使它像xargs一樣)。

你可以在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;
        }
    }
}

唯一的區別是你必須使用Perl樣式的正則表達式而不是GNU樣式。 他們並沒有太大的不同

您可以使用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