为什么 zgrep 不显示实际匹配项?
Why won't zgrep show the actual matches?
上下文
假设我有两个文件 a.txt
和 b.txt
,其中包含一些内容...
$ tail *.txt
==> a.txt <==
ABC
CDE
123
C
==> b.txt <==
C
321
EDC
CBA
让我们再想象一下,这些文件现在已经被放入一个 gzipped tarball 中...
$ tar -czf tarball.tgz *.txt
$ tar -tf tarball.tgz
a.txt
b.txt
目标
现在,我想 grep 浏览 tarball 中的文件。在匹配之前看到原始文件名和行号会很好,但我最重要的是想看到匹配的行。
我尝试了什么?
首先,我预计 zgrep 'pattern' tarball.tgz
会很简单。它确实告诉我是否有匹配项,它甚至可以计算匹配项,但我找不到打印匹配项的方法...
$ zgrep 'AB' tarball.tgz
Binary file (standard input) matches
$ zgrep 'C' tarball.tgz
Binary file (standard input) matches
$ zgrep -c 'AB' tarball.tgz
1
$ zgrep -c 'C' tarball.tgz
6
其次,我想 zcat
压缩包并对其使用常规 grep。但是,我仍然收到完全相同的 "Binary file (standard input) matches" 消息...
$ zcat tarball.tgz | grep 'C'
Binary file (standard input) matches
我猜 zcat
(和 zgrep
)做了一个 gunzip
但没有 tar -xf
?如果我查看 zcat
,我可以看到与刚刚完成 tar -c
...
相同的输出
$ zcat tarball.tgz
a.txt0000664�3���3���0000000001613554050266013370 0ustar useruserABC
CDE
123
C
b.txt0000664�3���3���0000000001613554050301013357 0ustar useruserC
321
EDC
CBA
$ tar -c *.txt
a.txt0000664�3���3���0000000001613554050266013370 0ustar useruserABC
CDE
123
C
b.txt0000664�3���3���0000000001613554050301013357 0ustar useruserC
321
EDC
CBA
所以最后,我得到了这个工作正常的解决方案:
$ tar -xOzf tarball.tgz | grep 'C'
ABC
CDE
C
C
EDC
CBA
当然,如果我现在要求文件名和行号,我没有得到任何有用的东西...
$ tar -xOzf tarball.tgz | grep -Hn 'C'
(standard input):1:ABC
(standard input):2:CDE
(standard input):4:C
(standard input):5:C
(standard input):7:EDC
(standard input):8:CBA
为了获得我想要的结果,我能想到的唯一方法是编写更多的脚本来提取 tarball 和 运行 grep
循环...
有没有好的(简单而简洁的)方法来做到这一点?
tar -czf
做了两件事:
- 将所有文件(在我的示例中恰好是文本)打包到一个 tar 文件(二进制文件)中;
- 将 tar 文件 gzip 成一个 gzip 压缩的 tar 文件。
正如我所怀疑的那样,zgrep
或 zcat
只会执行 gunzip
,并留下一个仍然是二进制的 tar 文件。这解释了我得到的所有输出。
简单的解决方案
最简单的方法是向 zgrep
添加一个选项:
-a, --text
Process a binary file as if it were text; this is equivalent to the --binary-files=text option.
这几乎和 tar -xOzf tarball.tgz | grep -Hn 'C'
一样好用,我们不获取单个文件名,行号覆盖整个 tar 输出。我们还得到一些噪音,即 tar
格式:
$ zgrep -Hna 'C' tarball.tgz
tarball.tgz:1:a.txt0000664�3���3���0000000001613554050266013370 0ustar jlehuenjlehuenABC
tarball.tgz:2:CDE
tarball.tgz:4:C
tarball.tgz:5:b.txt0000664�3���3���0000000001613554050301013357 0ustar jlehuenjlehuenC
tarball.tgz:7:EDC
tarball.tgz:8:CBA
这很容易记住,并且适用于例如。 grepping 日志,其中文件的第一行很少是有趣的匹配项。
最佳输出
现在,@Shawn 向我指出了 Unix StackExchange 上的 that answer。由此,我可以得出我最喜欢的选项:
$ tar -xf tarball.tgz --to-command='grep -Hn --label="$TAR_ARCHIVE/$TAR_FILENAME" C || true'
tarball.tgz/a.txt:1:ABC
tarball.tgz/a.txt:2:CDE
tarball.tgz/a.txt:4:C
tarball.tgz/b.txt:1:C
tarball.tgz/b.txt:3:EDC
tarball.tgz/b.txt:4:CBA
我可能会为此自己创建一些功能,因为打字并不有趣。不过,输出正是我想要的! :)
上下文
假设我有两个文件 a.txt
和 b.txt
,其中包含一些内容...
$ tail *.txt
==> a.txt <==
ABC
CDE
123
C
==> b.txt <==
C
321
EDC
CBA
让我们再想象一下,这些文件现在已经被放入一个 gzipped tarball 中...
$ tar -czf tarball.tgz *.txt
$ tar -tf tarball.tgz
a.txt
b.txt
目标
现在,我想 grep 浏览 tarball 中的文件。在匹配之前看到原始文件名和行号会很好,但我最重要的是想看到匹配的行。
我尝试了什么?
首先,我预计 zgrep 'pattern' tarball.tgz
会很简单。它确实告诉我是否有匹配项,它甚至可以计算匹配项,但我找不到打印匹配项的方法...
$ zgrep 'AB' tarball.tgz
Binary file (standard input) matches
$ zgrep 'C' tarball.tgz
Binary file (standard input) matches
$ zgrep -c 'AB' tarball.tgz
1
$ zgrep -c 'C' tarball.tgz
6
其次,我想 zcat
压缩包并对其使用常规 grep。但是,我仍然收到完全相同的 "Binary file (standard input) matches" 消息...
$ zcat tarball.tgz | grep 'C'
Binary file (standard input) matches
我猜 zcat
(和 zgrep
)做了一个 gunzip
但没有 tar -xf
?如果我查看 zcat
,我可以看到与刚刚完成 tar -c
...
$ zcat tarball.tgz
a.txt0000664�3���3���0000000001613554050266013370 0ustar useruserABC
CDE
123
C
b.txt0000664�3���3���0000000001613554050301013357 0ustar useruserC
321
EDC
CBA
$ tar -c *.txt
a.txt0000664�3���3���0000000001613554050266013370 0ustar useruserABC
CDE
123
C
b.txt0000664�3���3���0000000001613554050301013357 0ustar useruserC
321
EDC
CBA
所以最后,我得到了这个工作正常的解决方案:
$ tar -xOzf tarball.tgz | grep 'C'
ABC
CDE
C
C
EDC
CBA
当然,如果我现在要求文件名和行号,我没有得到任何有用的东西...
$ tar -xOzf tarball.tgz | grep -Hn 'C'
(standard input):1:ABC
(standard input):2:CDE
(standard input):4:C
(standard input):5:C
(standard input):7:EDC
(standard input):8:CBA
为了获得我想要的结果,我能想到的唯一方法是编写更多的脚本来提取 tarball 和 运行 grep
循环...
有没有好的(简单而简洁的)方法来做到这一点?
tar -czf
做了两件事:
- 将所有文件(在我的示例中恰好是文本)打包到一个 tar 文件(二进制文件)中;
- 将 tar 文件 gzip 成一个 gzip 压缩的 tar 文件。
正如我所怀疑的那样,zgrep
或 zcat
只会执行 gunzip
,并留下一个仍然是二进制的 tar 文件。这解释了我得到的所有输出。
简单的解决方案
最简单的方法是向 zgrep
添加一个选项:
-a, --text
Process a binary file as if it were text; this is equivalent to the --binary-files=text option.
这几乎和 tar -xOzf tarball.tgz | grep -Hn 'C'
一样好用,我们不获取单个文件名,行号覆盖整个 tar 输出。我们还得到一些噪音,即 tar
格式:
$ zgrep -Hna 'C' tarball.tgz
tarball.tgz:1:a.txt0000664�3���3���0000000001613554050266013370 0ustar jlehuenjlehuenABC
tarball.tgz:2:CDE
tarball.tgz:4:C
tarball.tgz:5:b.txt0000664�3���3���0000000001613554050301013357 0ustar jlehuenjlehuenC
tarball.tgz:7:EDC
tarball.tgz:8:CBA
这很容易记住,并且适用于例如。 grepping 日志,其中文件的第一行很少是有趣的匹配项。
最佳输出
现在,@Shawn 向我指出了 Unix StackExchange 上的 that answer。由此,我可以得出我最喜欢的选项:
$ tar -xf tarball.tgz --to-command='grep -Hn --label="$TAR_ARCHIVE/$TAR_FILENAME" C || true'
tarball.tgz/a.txt:1:ABC
tarball.tgz/a.txt:2:CDE
tarball.tgz/a.txt:4:C
tarball.tgz/b.txt:1:C
tarball.tgz/b.txt:3:EDC
tarball.tgz/b.txt:4:CBA
我可能会为此自己创建一些功能,因为打字并不有趣。不过,输出正是我想要的! :)