使用管道和字数(wc)然后修饰结果

using the pipe and word count (wc) then dress the result

我想修改我正在执行的 grep 的输出。

想象一个包含大量文本的文件 text.txt。然后我执行命令:

grep fred text.txt | wc -l
grep bob text.txt | wc -l
grep james text.txt | wc -l

我得到输出:

12
3
4

我想打印的输出是:

fred was found on 12 lines.
bob was found on 3 lines.
james was found on 4 lines.

我该怎么做?

您可以尝试在 awk 中进行操作(未测试,因为未提供示例),如果您对 awk 没问题,则不需要 运行 很多 grep + wc 命令它可以在单个 awk 程序本身中完成。

awk '
{
  a["fred"]+=gsub(/fred/,"&")
  a["bob"]+=gsub(/bob/,"&")
  a["james"]+=gsub(/james/,"&")
}
END{
  for(i in a){
    print i" was found on "a[i]" lines."
  }
}' Input_file

在shell脚本中,使用grep -c计算行数:

for name in fred bob james
do
    echo "$name was found on $(grep -c $name text.txt) lines."
done

这会运行一半的进程。这假设您最终不想搜索带有空格 ('lucy anne') 或引号 ("o'reilly") 的名称——如果您需要更通用的名称,您也可以在命令替换中使用双引号 $name 时需要更加小心。

但是,您可以使用 awk(或 Perl 或 Python,或……)扫描一次文件,如果文件很大,这可能会节省很多:

awk '
    /fred/  { count["fred"]++ }
    /bob/   { count["bob"]++ }
    /james/ { count["james"]++ }
   END      { for (name in count) print name, "was found on", count[name], "lines." }
   ' text.txt

这与 by RavinderSingh13 类似,但它只计算名字出现的行数,而不是出现的总次数(所以如果一行包含“bob was bobbing on the water all discombobulated”,它会计算在内1 行,而不是出现 3 次)。请注意,搜索既不是 case-insensitive(“Bob”不会被计算在内),也不会被限制为匹配 'words' 以获取任何合理的单词定义。这些注释也适用于 grep 解决方案,但您也可以使用诸如 -i 之类的选项来匹配 case-insensitivity(来自 POSIX)和 -w 来匹配单词( GNU grep 和其他一些,例如 BSD 和 macOS X)。