我正在使用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>
我的第一个虽然去了awk
但这比我认为的需要做的工作更多,拆分并重新加入生产线。
sed替代方案非常简洁
用 2 个空格和一个冒号替换第一个冒号。
关于带冒号对话的文件名:
阅读 GNU grep 手册页:使用
-Z
选项:“输出零字节(ASCII NUL 字符)而不是通常跟随文件名的字符。”所以:
如果您只需要一个包含与模式匹配的文本的文件名列表,例如“zorro”,并且您打算将这些文件名用于另一个程序,那么您可以执行以下操作来创建一个包含文件名的 bash 数组,并避免使用鼠标进行大量手动复制粘贴。:
mapfile
是一个 bash 内置命令,用于从标准输入填充数组。在这种情况下,标准输入来自grep
作为进程替换运行。我用-d ''
withmapfile
来告诉它输入将由 NUL 字符分隔,并-Z
输出grep
一个以 NUL 分隔的匹配文件名列表。这适用于任何文件名,无论名称中有什么字符 - 包括冒号、空格、换行符和 shell 元字符。您可以使用 来查看数组中
declare -p myfiles
的内容,或者将数组的元素用作另一个程序(例如printf '%s\'n' "${myfiles[@]}"
)的 args,或者在像for f in "${myfiles[@]}"; do echo "$f" ; done
.注意:grep 的
-l
选项将在第一次匹配后退出(与-m
选项相同),这将加快在文件中搜索字符串出现在文件早期的文件中的搜索。在没有出现模式的文件中,它仍然需要读取整个文件。顺便说一句,如果您使用该
-I
选项的原因是您希望避免使用二进制文件(例如 TeX 的 .pdf 或 .dvi 输出),那么您可以find
使用grep -r
. 例如:如果您需要更复杂的选择标准,超出 grep 的能力,那么您可以使用 awk 或 perl 或其他任何东西来代替 grep。例如,如果您只想要文件第 3 行出现“zorro”的文件名:
这只是一个简单的示例 - 如果您可以考虑一个标准并将其编写为 perl(或 awk 或 python 或其他)脚本,那么您可以使用它来选择性地填充数组。您可以使用任何命令,或任何长而复杂的命令管道,只要它将文件名打印到标准输出并以 NUL 字符分隔即可。
注意:
close(ARGV)
关闭当前文件并跳到下一个,如果有的话,文件名是否被打印。这意味着它永远不必读取超过三行的任何文件,因此如果您有很多大文件要搜索,速度会快得多。注 2:
\Q
and\E
是 perl 进行固定字符串搜索的方式,类似于-F
grep。如果您使用的是 awk,则可以对该index()
函数执行类似的操作。