我想从压缩的.gz文件中的文件中获取几行。
.gz文件包含许多txt文件,我想在所有这些txt文件中搜索字符串,并且需要将前3行作为输出,包括当前行(搜索字符串所在的位置)。
我尝试了zgrep
并获得了行号,但是当我使用head
或tail
命令时它会给出一些垃圾值。我认为我们不能将head
或tail
命令用于包含多个文件的压缩文件。
请建议是否有简单的方法?
答案 0 :(得分:5)
如何实现这一目标的本质是获取tarball中的文件名称进行搜索,并提取要搜索的内容,而不提取任何其他内容。因为我们不想写入文件系统,所以我们可以使用-O
标志来提取标准输出。
tar -tzf file.tar.gz | grep '\.txt' | xargs tar -Oxzf file.tar.gz | grep -B 3 "string-or-regex"
将连接.tar.gz中名称以“.txt”结尾的所有文件,并将grep
连接到给定字符串,同时输出前3行。它不会告诉你任何匹配来自tarball中的哪个文件,并且“前三行”实际上可能来自上一个文件。
您可以改为:
for file in $(tar -tzf file.tar.gz | grep '\.txt'); do
tar -Oxzf file.tar.gz "$file" | grep -B 3 --label="$file" -H "string-or-regex"
done
它将尊重文件边界,并报告文件名,但效率低得多。
(-z
告诉tar
压缩gzip
。-t
列出内容。-x
提取。-O
重定向到标准输出比较文件系统。较早的tar
可能没有-O
或-z
标志,并且希望标记没有-
:例如tar tz file.tar.gz
)
好的,所以你有一个无法使用的grep。我们可以用awk解决这个问题!
#!/usr/bin/awk -f
BEGIN { context=3; }
{ add_buffer($0) }
/pattern/ { print_buffer() }
function add_buffer(line)
{
buffer[NR % context]=line
}
function print_buffer()
{
for(i = max(1, NR-context+1); i <= NR; i++) {
print buffer[i % context]
}
}
function max(a,b)
{
if (a > b) { return a } else { return b }
}
与grep -B不同,这不会合并相邻的匹配,因此可以重复这些行 在两个不同的比赛中有3行。
答案 1 :(得分:0)
这可能是tar文件的一个gzip吗?最简单的只是提取整个事物并在提取的文件上使用常规工具。