假设有文件
foo bar cat dog
foo foo cat bar
bar foo foo foo
我们如何 grep 查找出现一定次数的行,例如,foo
如果次数是1只应打印示例文件中的第一行?
答案1
$ grep 'foo' file | grep -v 'foo.*foo'
首先挑出包含 的所有行foo
,然后删除所有带有 的行,foo
然后删除foo
该行中的另一行。
如果所有行至少包含一个foo
(如您的示例中所示),您可以跳过第一个grep
.
对于“我如何grep
准确地氮字符串出现?”: grep
对于至少包含以下内容的行氮匹配,然后删除行N+1匹配(或更多)。
答案2
对于一般情况 - 仅打印精确的行氮您可以使用awk
'sgsub()
来返回编号。进行的替换并打印该行(如果没有)。符合要求,例如打印恰好出现 3 次的行:
awk '{l=$0;t=gsub(/foo/,"",l)}t==3' infile
另一种方式sed
:
sed 's/foo/&/3
t x
: k
d
: x
s/foo/&/4
t k' infile
这会尝试将第三次出现的内容替换为自身,如果失败,则删除该行d
;如果成功,它会分支到: x
尝试用自身替换第四次出现的地方 - 如果成功(这意味着有超过 3 次出现),它会分支到: k
(以便该行也被删除),否则它不执行任何操作(除了自动打印该行之外)。 ..)
对于示例中的特定情况(仅出现一次的行),您还可以使用
sed '/foo/!d;/foo.*foo/d' infile
或类似的东西:
pcregrep '^(?:(?!foo).)*foo((?:(?!foo).)*)$' infile
答案3
使用grep -c
来计数:
while read line; do [[ $(echo $line | sed 's/ /\n/g' | grep -c foo) == 2 ]] && echo "$line"; done < file.txt
答案4
另一种选择可能是使用perl
,例如将匹配项推送到列表上下文中,然后在标量上下文中测试它:
perl -ne 'my $count = () = $_ =~ /foo/g; print if $count == 1' file
或没有显式标量变量
perl -ne 'print if ( () = $_ =~ /foo/g ) == 1' file
这种方法很容易推广到返回具有任何其他所需数量的匹配项的行。