[英]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
。
关于find
, awk
或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.