假设我有两个文件a.txt
和b.txt
,其中包含一些内容...
$ tail *.txt
==> a.txt <==
ABC
CDE
123
C
==> b.txt <==
C
321
EDC
CBA
让我们想象一下,文件现在已经放在压缩的tarball中了。
$ tar -czf tarball.tgz *.txt
$ tar -tf tarball.tgz
a.txt
b.txt
现在,我想遍历压缩包中的文件。在匹配之前查看原始文件名和行号会很好,但是我最重要的是要查看匹配的行。
首先,我希望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。但是,我仍然得到完全相同的“二进制文件(标准输入)匹配项” 消息...
$ 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
要想得到想要的结果,我能想到的唯一方法就是要花费更多的脚本来提取压缩包并循环运行grep
...
是否有一种简便(简洁)的好方法?
答案 0 :(得分:0)
tar -czf
做两件事:
正如我一直怀疑的那样,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
我可能会为此创建一些函数,因为键入并不有趣。输出正是我想要的! :)