递归搜索模式,然后为每个匹配打印出特定的序列:行号、文件名和无文件内容

Joh*_*son 6 grep bash find awk

我所追求的几乎与可以在此处找到的完全相同,但我希望结果中的格式为“行号,分隔符,文件名,换行符”,从而在行的开头显示行号,而不是在文件名之后,并且不显示包含匹配项的行。

这种格式更可取的原因是

  • (a)文件名可能很长而且很神秘,并且包含工具用来将文件名与行号分开的分隔符,这使得使用 awk 来实现这一点非常困难,因为文件内的模式也可能包含相同的分隔符. 此外,行首的行号将比它们出现在文件名之后更好地对齐。这种所需格式的另一个原因是
  • (b)匹配模式的行可能太长并且弄乱了标准输出上显示的输出上的每行一行属性(并且在标准输出上查看输出比必须保存到文件并使用类似的工具要好vi 以查看输出文件中每行一行)。

    如何递归搜索目录以查找模式并仅打印出文件名和行号

既然我已经提出了要求,请考虑一下:

  1. 我正在使用的 Linux 主机上没有安装 Ack,所以我无法使用它。

  2. 如果我执行以下操作,shell 将执行find .并用从当前工作目录开始并向下递归的绝对路径列表替换“find .”:

    grep -n PATTERN $(find .)
    
    Run Code Online (Sandbox Code Playgroud)

    然后 -n 打印行号,但不是我想要的地方。此外,由于某种原因我不明白,如果目录名称包含 PATTERN,那么除了包含该模式的常规文件之外,grep 还会匹配它。这不是我想要的,所以我使用:

    grep -n PATTERN $(find . -type f)
    
    Run Code Online (Sandbox Code Playgroud)

    我还想更改此命令,以便将 find 的输出动态传递给 grep。不必先构建完整的绝对路径列表,然后将其中的大部分传递给 grep,而是在构建列表时将每一行传递给 grep,所以我尝试了:

    find . -exec grep -n PATTERN  '{}' \;
    
    Run Code Online (Sandbox Code Playgroud)

    根据 ,这似乎是正确的语法,man page但是当我发出此命令时,Bash shell 的执行速度要慢大约 100 倍,所以这不是要走的路。

鉴于我所描述的,我如何执行类似于此命令的操作并获得所需的格式。我已经列出了与相关帖子相关的问题。

slm*_*slm 4

使用 grep

为什么不能只使用-rswitch togrep来递归文件系统而不是使用find?我还会使用 2 个附加开关来代替-n开关。

$ grep -rHn PATTERN <DIR> | cut -d":" -f1-2
Run Code Online (Sandbox Code Playgroud)

例子#1

$ grep -rHn PATH ~/.bashrc | cut -d":" -f1-2
/home/saml/.bashrc:25
Run Code Online (Sandbox Code Playgroud)

细节

  • -r- 递归搜索文件+目录
  • -H- 如果文件名匹配(限制性比 少-l),则打印文件名,即它与grep的其他开关一起使用
  • -n- 显示匹配的行号

例子#2

$ grep -rHn PATH ~/.bash* | cut -d":" -f1-2
/home/saml/.bash_profile:10
/home/saml/.bash_profile:12
/home/saml/.bash_profile_askapache:99
/home/saml/.bash_profile_askapache:101
/home/saml/.bash_profile_askapache:118
/home/saml/.bash_profile_askapache:166
/home/saml/.bash_profile_askapache:218
/home/saml/.bash_profile_askapache:250
/home/saml/.bash_profile_askapache:314
/home/saml/.bash_profile_askapache:2317
/home/saml/.bash_profile_askapache:2323
/home/saml/.bashrc:25
Run Code Online (Sandbox Code Playgroud)

使用查找

$ find . -exec sh -c 'grep -Hn PATTERN "$@" | cut -d":" -f1-2' {}  +
Run Code Online (Sandbox Code Playgroud)

例子

$ find ~/.bash* -exec sh -c 'grep -Hn PATH "$@" | cut -d":" -f1-2' {}  +
/home/saml/.bash_profile:10
/home/saml/.bash_profile:12
/home/saml/.bash_profile_askapache:99
/home/saml/.bash_profile_askapache:101
/home/saml/.bash_profile_askapache:118
/home/saml/.bash_profile_askapache:166
/home/saml/.bash_profile_askapache:218
/home/saml/.bash_profile_askapache:250
/home/saml/.bash_profile_askapache:314
/home/saml/.bash_profile_askapache:2317
/home/saml/.bash_profile_askapache:2323
/home/saml/.bashrc:25
Run Code Online (Sandbox Code Playgroud)

如果您确实想使用,find您可以执行类似的操作,grep在使用 .find 文件找到文件后执行find