我只需要grep不包含use Test::More tests => 1;
字符串并且具有多于10
字符串的文件。该怎么做?
用于打印不匹配文件名的典型解决方案是使用grep -L
标志,用于计数行号的典型解决方案是使用wc -l
。但是如何将它们结合起来?
grep -rL "use Test::More tests => 1;" t | wc -l
在grep输出中仅显示结果数量。
答案 0 :(得分:1)
grep -L将列出不包含搜索字符串的文件。因此,grep -L是您解决方案的基本组成部分。但是,通过将结果传递给wc -l,您仅在计算不包含搜索字符串的所有文件。这不是您想要的那样。相反,您只想列出没有搜索字符串且行数超过10行的文件。考虑以下代码:
grep -rL "use Test::More tests => 1;" t | xargs wc -l | awk '$1 > 10 {print $2}'
这里最有趣的命令是xargs,它将标准输入中的输出作为参数传递给下一个命令:wc -l。现在,wc -l将为您提供行数列表和文件名。这将通过管道传递到awk,awk将选择第一列值大于10的所有行,并仅显示第二列。
您可能会发现单独运行命令以查看传递到下一个管道的输出很有用:
grep -rL "use Test::More tests => 1;" t | xargs echo
grep -rL "use Test::More tests => 1;" t | xargs wc -l
grep -rL "use Test::More tests => 1;" t | xargs wc -l | awk '$1 > 10 '
然后将它们放在一起:
grep -rL "use Test::More tests => 1;" t | xargs wc -l | awk '$1 > 10 {print $2}'
答案 1 :(得分:1)
您可以在流程替换中使用find
来运行循环:
while IFS= read -d '' -r file; do
grep -Fq 'use Test::More tests => 1;' "$file" &&
(( $(wc -l < "$file") >= 10 )) && echo "$file"
done < <(find . -type f -print0)
此代码处理带有空格,换行符或glob字符的文件名。
答案 2 :(得分:0)
TL; DR:
awk 'FNR==1 { found=0 }
/use\s+Test::More\s+tests\s*=>\s*1\s*;/ { found=1; }
FNR > 10 { if ( found ) { print FILENAME; nextfile } }' t/*
使用和不使用
grep
来破坏它。
要仅获取多于10行的文件,请执行以下操作:
awk 'FNR==11 { print FILENAME; nextfile; }' *
FNR
是“记录文件号”,即我们在此文件的哪一行。如果是11,则超过十行,因此打印FILENAME并移至下一个文件。
您可以使用
将没有搜索字符串的文件列表保存到数组中declare -a lst=( $( grep -rL "use Test::More tests => 1;" t ) )
然后您可以使用
报告十行以上的内容awk 'FNR==11 { print FILENAME; nextfile; }' "${lst[@]}"
尽管我建议您不要过于僵化-有时人们会用手指摸索或对齐东西等,所以可以这样尝试:
declare -a lst=( $( grep -rLE "use\s+Test::More\s+tests\s*=>\s*1\s*;" t ) )
awk 'FNR==11 { print FILENAME; nextfile; }' "${lst[@]}"
您可以通过子呼叫在一行中完成所有操作,就像这样:
awk 'FNR==11 { print FILENAME; nextfile; }' $( grep -rLE "use\s+Test::More\s+tests\s*=>\s*1\s*;" t )
这也避免了不必要的无关执行。如果您想真正地减少它,我们可以将它们全部放在一个awk
中,但是如果我们需要遍历一个以上的子目录,则应该使用grep
或find
无论如何。否则,
如果您仅搜索
t
目录中的文件,而不是其子目录-
awk 'FNR==1 { found=0 }
/use\s+Test::More\s+tests\s*=>\s*1\s*;/ { found=1; }
FNR > 10 { if ( found ) { print FILENAME; nextfile } }' t/*
您可以优化此范围,例如,正在检查的所有文件都具有*.pl
之类的名称,这样可以避免尝试读取目录和其他类似的丑陋内容。同样,这可能会因文件名奇/零而混淆。
但是 IF 您真正想要的是包含十个以上 distinct 行的文件,这些行中没有令牌字符串,然后将
awk
更改为-
awk '1 == FNR { cnt=0; found=0; }
hit[$0] { next; }
/use\s+Test::More\s+tests\s*=>\s*1\s*;/ { found=1; }
{ hit[$0]=1; cnt++;
if ( 10 < cnt ) { print FILENAME; nextfile; }
}
' t/*
是的,如果您愿意,可以将所有内容压缩成一行, ew ,不要,大声笑。