Unix脚本搜索压缩的.gz文件

3

我想要从一个压缩的 .gz 文件中获取几行文本。该 .gz 文件包含许多 txt 文件,我想在所有这些 txt 文件中搜索一个字符串,并需要获得前三行作为输出,包括当前行(其中存在搜索字符串)。

我尝试使用 zgrep 并得到了行号,但是当我使用 headtail 命令时,它会给出一些垃圾值。我认为我们不能将 headtail 命令与包含多个文件的压缩文件一起使用。

请建议是否有任何简单的方法?


能否将标题改为清晰表明这是一个.tar.gz文件?你想要将前三行仅放在一个文件中,还是允许它从之前的文件中报告一行? - wnoise
从同一文件/相同文件中获取前三行。 - CFUser
压缩文件不等于tar包。请修正措辞。 - Conrad Meyer
2个回答

5
实现这一目标的关键是获取tarball中要搜索的文件名,并提取它们的内容进行搜索,而不会提取其他任何内容。因为我们不想写入文件系统,所以可以使用-O标志来提取到标准输出。 tar -tzf file.tar.gz | grep '\.txt' | xargs tar -Oxzf file.tar.gz | grep -B 3 "string-or-regex"将连接所有以“.txt”结尾的.tar.gz文件中的文件,并对给定的字符串进行grep,还会输出前三行。它不会告诉您匹配来自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 不同,这不会合并相邻的匹配项,因此可能重复显示与两个不同匹配项之间相隔三行以内的行。

它支持-C吗?获取之后的3行也是问题吗? - wnoise
很遗憾,也没有C语言。 - CFUser
1
@CFUser:如果grep不支持-B选项,你就必须使用awksed或Perl来保持一个移动的行窗口,以便在找到匹配项时输出。GNU tar支持--wildcards选项,这使得每个版本中第一个tar|grep命令都是不必要的。其他版本的tar可能支持通配符,也可能需要开启一个开关才能使用。 - Dennis Williamson
只要你想要GNU tar,为什么不安装GNU coreutils并使用gtar/ggrep呢?但总的来说,我喜欢awk的答案=)。 - Conrad Meyer

0

这可能是一个tar文件的gzip压缩包吗?最简单的方法就是解压整个文件并使用提取后的文件上的常规工具。


2
是的,这是一个tar文件的gzip压缩包。我无法解压它,因为其中包含了大量的文件,将会导致磁盘空间问题。 - CFUser

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接