我正在看源文件。实际上对于 PureBasic,但无论哪种语言,都涉及到共同的元素。就我而言,该命令将是 cover extensions pb
、pbi
、pbf
和pbp
:
find . -name "*.pb*" -exec grep -Hnr ... \;
问题是,这可能会导致很长的行,并且过于紧凑而不易阅读,因为它们包含full/path/filename.ext:ln#:contents of that line
.
我想做两件事之一:要么完全切断路径(最后一个/
在第一个之前:
)并离开:
filename.ext:ln#:contents of that line
或分割线,这样我就有:
full/path/filename.ext:
ln#:contents of that line
无论哪种方式都会使结果更具可读性。您甚至可以将其拆分为您拥有的位置:
full/path/filename.ext:ln#:
contents of that line
以提高可读性。我很灵活。它可以是其中任何一个。它甚至不必局限于一行命令或这些特定命令。
我已经尝试了我能找到的所有列出的技术,包括find
,grep
但sed
我无法让组合完全达到我想要的效果。
答案1
根据您的描述,我认为您正在这样做(我将其分成四行以避免水平滚动)
>tmp.txt;
find . -type f -name "*.pb*" \
-exec grep -Hn pattern "{}" ";" >>tmp.txt;
cat tmp.txt | more
如果您使用 Gnu find,则可以使用;-execdir
代替-exec
这将导致grep
命令从目标文件的目录中执行,结果是文件名将相对于它所在的目录。(即./filename.ext
)。那不是相当你所要求的,但它非常接近,并且还有其他充分的理由使用-execdir
.
-execdir grep -Hn pattern "{}" ";" # See note 1
另一种选择是使用中间 shell 来编辑文件名标签。这需要 Gnugrep
选项--label
:
-exec bash -c 'grep -Hn --label="$(basename "$1")" pattern "$1"' \
_ "{}" ";"
这对于操作系统来说是相当长的时间和更多的工作,但它确实消除了./
.
对于第二个选项,您可以通过管道传输整个输出sed
,在每行的第一行(或第二行)之后插入换行符:
。
find . -type f -name "*.pb*" \
-exec grep -Hn pattern "{}" ";" |
sed 's/:/&\n/' >>tmp.txt.
或(第二个冒号):
find . -type f -name "*.pb*" \
-exec grep -Hn pattern "{}" ";" |
sed 's/:[^:]*:/&\n/' >>tmp.txt.
笔记
告诉 grep 进行递归搜索 (
-r
) 是没有意义的,因为你永远不会给它一个目录作为参数。find
已经递归地找到了所有文件。所以我从所有示例中删除了该选项。cat tmp.txt | more
是猫的无用使用(UUOC)。只需使用more tmp.txt
.使用 Gnu find 替换
;
为+
以提高效率(除了使用 的示例bash -c
)。
答案2
从你要寻找的前提出发图案在您的文件中,以下是针对您建议的每个布局的解决方案:
删除路径名的前导部分
find . -name '*.pb*' -type f -execdir grep -Hn 'PATTERN' {} \; | cut -c3- >tmp.txt more tmp.txt
当使用
execdir
它引用的程序时,总是从目标目录调用,并且当前文件的路径名以./
.只是从路径名中cut -c3-
删除前导。./
用路径名分割行,后跟行号和匹配项
find . -name '*.pb*' -type f -exec grep -Hn 'PATTERN' {} \; | sed 's/:/:\n/' >tmp.txt
使用路径名和行号分割行,然后匹配
find . -name '*.pb*' -type f -exec grep -Hn 'PATTERN' {} \; | sed 's/^\([^:]*:[^:]*:\)/\1\n/' >tmp.txt
在这里,
sed
模式在第二个冒号处分裂(RE 读作从该行的开头开始。匹配零个或多个非冒号字符,后跟冒号。然后再次。现在将匹配项替换为自身,然后换行)。
如果您的文件名包含冒号或换行符,这些解决方案都无法正常工作。
答案3
您可以尝试使用awk
而不是grep
,例如仅打印基本名称:
find . -name '*.pb*' -exec awk 'function basename(file) {
sub(".*/", "", file)
return file
}
/pattern/{
print basename(FILENAME)":"FNR":"$0
}' {} +
并分割路径/行内容:
find . -name '*.pb*' -exec awk '/pattern/{print FILENAME"\n"FNR":"$0}' {} +
或者
find . -name '*.pb*' -exec awk '/pattern/{print FILENAME":"FNR":\n"$0}' {} +
如果您只想打印文件名一次,后跟该文件中的所有匹配行,并带有两个grep
s:
find . -name '*.pb*' -exec grep -l pattern {} \; -exec grep -n pattern {} \;
这些应该适用于所有类型的文件名(即使是包含冒号的文件名)...
答案4
使用grep -l
find . -type f -exec grep -ilHn --color=always 'searchphrase' {} \;