如何在 grep 输出的文件名后添加空格?

如何在 grep 输出的文件名后添加空格?

我用来grep搜索文件内的匹配模式,并从输出中复制其文件名。由于我经常进行此操作,因此我最终:也可能会进行复制。因此,是否可以在第一个匹配的半列或文件名结尾之前添加两个空格?

$ grep -Hrn -e "zorro" --color=always --exclude-dir=dir -I -F . | \
    cut -c 11- | awk '$0="\033[33;35m"$0' | tr -s '[:space:]'
doo.tex:1:zorro alper alper alper skfjsdlkfj dslfj dslkj

想要的输出:

doo.tex  :1:zorro alper alper alper skfjsdlkfj dslfj dslkj
        ^
  <two space added>

答案1

我的第一个虽然去了

awk -F: -vOFS=: '{$1 = $1 "  "; print}'

但我认为这比需要做的工作更多,分裂和重新加入队伍。

替代方案非常简洁

sed 's/:/  :/'

更换第一的带有 2 个空格和一个冒号的冒号。


关于带冒号对话的文件名:

阅读 GNU grep 手册页:使用-Z选项:“输出零字节(ASCII NUL 字符)而不是通常跟在文件名后面的字符。”

所以:

# .......v
grep -HrnZ -e "zorro" --color=always --exclude-dir=dir -I -F . | \
  perl -pe 's/\0/  :/'

答案2

如果您需要的只是包含与模式匹配的文本的文件名列表,例如“zorro”,并且您打算在另一个程序中使用这些文件名,那么您可以执行如下操作来创建包含文件名的 bash 数组,并避免大量用鼠标手动复制粘贴:

mapfile -d '' -t myfiles < <(grep -IFlZr zorro ./)

mapfile是一个 bash 内置命令,用于从 stdin 填充数组。在这种情况下,标准输入来自于grep作为流程替代。我使用-d ''withmapfile告诉它输入将由 NUL 字符分隔,并-Z使用 withgrep来输出以 NUL 分隔的匹配文件名列表。这将与任何文件名,无论名称中包含什么字符 - 包括冒号、空格、换行符和 shell 元字符。

您可以使用 来查看数组中的内容declare -p myfiles,或者使用数组的元素作为另一个程序的参数(例如printf '%s\'n' "${myfiles[@]}"),或者在类似 的循环中for f in "${myfiles[@]}"; do echo "$f" ; done

注意:grep 的-l选项将在第一次匹配后退出(与选项相同-m),这将加快搜索字符串出现在文件早期的文件中的搜索速度。在没有出现模式的文件中,它仍然需要读取整个文件。

顺便说一句,如果您使用该选项的原因-I是您想避免二进制文件(例如 TeX 的 .pdf 或 .dvi 输出),那么您可以find使用grep -r.例如:

mapfile -d '' -t myfiles < <(find . -type f -name '*.tex' -exec grep -lZF zorro {} +)

如果您需要更复杂的选择标准,超出 grep 的能力,那么您可以使用 awk 或 perl 或其他任何东西来代替 grep。例如,如果您只需要文件第 3 行出现“zorro”的文件名:

mapfile -d '' -t myfiles < <(find . -type f -name '*.tex' \
  -exec perl -n -e 'if ($. == 3) {
                      printf "%s\0", $ARGV if (/\Qzorro\E/);
                      close(ARGV);
                    }' {} +)

这只是一个简单的例子 - 如果您可以想到一个标准并将其编写为 perl(或 awk 或 python 或其他)脚本,那么您可以使用它来有选择地填充数组。您可以使用任何命令或任何长且复杂的命令管道,只要它将文件名打印到标准输出并用 NUL 字符分隔即可。

注意:close(ARGV)关闭当前文件并跳转到下一个文件(如果有),无论文件名是否打印。这意味着它永远不需要读取任何文件的三行以上,因此如果您要搜索大量大文件,速度会快得多。

注2:\Qand\E是perl 进行固定字符串搜索的方式,类似于-Fgrep。如果您使用 awk,您可以使用该index()函数执行类似的操作。

相关内容