如何为多个匹配仅打印一次匹配的文件名(不只打印文件名)

如何为多个匹配仅打印一次匹配的文件名(不只打印文件名)

我同时从多个日志中抓取内容grep -Er

但我只想匹配一次文件前缀。

我想要实现的目标有点像ls -lr(匹配文件一次,然后是每个所述文件的所有匹配行)

我在手册上没有找到这个选项。

我可以只用 grep 来实现它吗?如何 ?

答案1

grep据我所知,没有任何实现。-r本身并不是一个标准选项。您可以轻松地在脚本或函数中实现一个用于find查找文件并perl进行匹配和报告文件路径的函数。

rPgrep() {
  local pattern="$1"
  shift
  find -- "$@" -type f -print0 |
    perl -C -0se '
      @ARGV = <STDIN>;
      $ /= "\n";
      while (<<>>) {
        if (/$pattern/) {
          unless ($header_already_printed) {
            print "\n" if defined $header_already_printed;
            print "$ARGV:\n";
            $header_already_printed = 1;
          }
          print;
        }
        $header_already_printed &&= 0 if eof;
      }' -- -pattern="$pattern"
}

进而:

rPgrep pattern some/dir some/other/dir or/regular/file

如果您还想查看常规文件的符号链接,请替换-type-xtype(假设为 GNU )。find或者添加-L选项,以便在像 GNU (而不是)find那样沿目录树下降时也遵循符号链接。grep -R-r

作为奖励,您可以获得 perl 正则表达式(类似于一些grep支持的-P),而不是有限的延长那些你得到的-E

不区分大小写的匹配 ( -i) 或单词匹配 ( -w) 或反向匹配 ( -v) 或整行匹配 ( -x) 可以使用正则表达式语法 ( (?i), \b, (?!...), ^...\z) 来完成,但对于其他grep选项 ( -n, -l,-F或一些非标准扩展,如-o// -A/ -B) -C..., perl 代码必须修改。

您还可以执行以下操作:

find . -type f -exec grep -q pattern {} ';' \
               -exec printf '\n%s:\n' {} ';' \
               -exec grep pattern {} ';'

但这意味着每个文件最多运行三个命令,因此效率非常低。

对于 GNU find-exec printf '\n%s:\n' {} ';'可以替换为-printf '\n%p:\n'.

相关内容