使用 find -exec grep,如何仅打印基本名称或将文件名/行内容拆分为单独的行?

old*_*oxx 5 grep find

我正在看源文件。实际上对于 PureBasic,但无论哪种语言,都涉及到共同的元素。就我而言,该命令将是 cover extensions pbpbipbfpbp

find . -name "*.pb*" -exec grep -Hnr ... \;
Run Code Online (Sandbox Code Playgroud)

问题是,这可能会导致很长的行,并且过于紧凑而不易阅读,因为它们包含full/path/filename.ext:ln#:contents of that line.

我想做两件事之一:要么完全切断路径(最后一个/在第一个之前:)并离开:

filename.ext:ln#:contents of that line
Run Code Online (Sandbox Code Playgroud)

或分割线,这样我就有:

full/path/filename.ext:    
ln#:contents of that line
Run Code Online (Sandbox Code Playgroud)

无论哪种方式都会使结果更具可读性。您甚至可以将其拆分为您拥有的位置:

full/path/filename.ext:ln#:  
contents of that line
Run Code Online (Sandbox Code Playgroud)

以提高可读性。我很灵活。它可以是其中任何一个。它甚至不必局限于一行命令或这些特定命令。

我已经尝试了我能找到的所有列出的技术,包括findgrepsed我无法让组合完全达到我想要的效果。

ric*_*ici 1

根据您的描述,我认为您正在这样做(我将其分成四行以避免水平滚动)

>tmp.txt;
find . -type f -name "*.pb*" \
     -exec grep -Hn pattern "{}" ";" >>tmp.txt;
cat tmp.txt | more
Run Code Online (Sandbox Code Playgroud)

如果您使用 Gnu find,则可以使用;-execdir代替 -exec这将导致grep命令从目标文件的目录中执行,结果是文件名将相对于它所在的目录。(即./filename.ext)。这并不完全是您所要求的,但它非常接近,并且还有其他充分的理由使用-execdir.

     -execdir grep -Hn pattern "{}" ";"      # See note 1
Run Code Online (Sandbox Code Playgroud)

另一种选择是使用中间 shell 来编辑文件名标签。这需要 Gnugrep选项--label

     -exec bash -c 'grep -Hn --label="$(basename "$1")" pattern "$1"' \
           _ "{}" ";"
Run Code Online (Sandbox Code Playgroud)

这对于操作系统来说是相当长的时间和更多的工作,但它确实消除了./.

对于第二个选项,您可以通过管道传输整个输出sed,在每行的第一行(或第二行)之后插入换行符:

find . -type f -name "*.pb*" \
     -exec grep -Hn pattern "{}" ";" |
sed 's/:/&\n/' >>tmp.txt.
Run Code Online (Sandbox Code Playgroud)

或(第二个冒号):

find . -type f -name "*.pb*" \
     -exec grep -Hn pattern "{}" ";" |
sed 's/:[^:]*:/&\n/' >>tmp.txt.
Run Code Online (Sandbox Code Playgroud)

笔记

  1. 告诉 grep 进行递归搜索 ( -r) 是没有意义的,因为你永远不会给它一个目录作为参数。find已经递归地找到了所有文件。所以我从所有示例中删除了该选项。

  2. cat tmp.txt | more是猫的无用使用(UUOC)。只需使用more tmp.txt.

  3. 使用 Gnu find 替换;+以提高效率(除了使用 的示例bash -c)。