仅处理Tcl中gzip文件的前n行

仅处理Tcl中gzip文件的前n行,tcl,Tcl,我需要从文本文件的前n行(大约50行)中提取一些字符串值。在某些情况下,文件是gzip文件,而在某些情况下则不是 目前,我正在使用以下方法读取文件,但这会读取整个文件,并且处理非常大的文件的速度很慢 set f [open "| zcat -f $filename" r] 如果文件不是gzip文件,那么这似乎可以正常工作,而且速度相当快 set f [open "| head -n 50 $filename" r] 但是当它被gzip压缩时,我似乎不能只看到前n行。我已经试过了,但是在tcl

我需要从文本文件的前n行(大约50行)中提取一些字符串值。在某些情况下,文件是gzip文件,而在某些情况下则不是

目前,我正在使用以下方法读取文件,但这会读取整个文件,并且处理非常大的文件的速度很慢

set f [open "| zcat -f $filename" r]
如果文件不是gzip文件,那么这似乎可以正常工作,而且速度相当快

set f [open "| head -n 50 $filename" r]
但是当它被gzip压缩时,我似乎不能只看到前n行。我已经试过了,但是在tclsh上出现了一个错误

set f [open "| zcat -f $filename | head -n 50" r]
set data [read $f]
close $f

%child killed: write on pipe with no readers
我可以尝试捕捉错误并继续,因为它似乎确实将数据推入$data变量,但我想知道我在这里是否做了非法的事情

或者,是否有一种纯Tcl的方法来实现这一点?

错误来自关闭,原因是zcat在写入所有行之前被信号SIGPIPE停止。这是意料之中的,你可以安全地抓住它并忽略它。把钩子挂在门上

在Tcl 8.6中,但不是任何以前的版本,也不是Tcl的独立zlib包中;这是我们在将包导入Tcl时添加的功能,您可以在纯Tcl中完成

set f [open $filename]
zlib push gunzip $f

# Read those lines! This oneliner is a hack!
set lines [lmap - [lrepeat 50 -] {gets $f}]

# NB: We don't need to put a catch around this now
close $f

zlib命令提供压缩和解压缩功能;zlib push用于向通道添加压缩或解压缩,例如在本例中应用了gunzip通道过滤器。

谢谢,您掌握了丰富的Tcl知识。这是难以置信的快。它实际上比head命令运行得更快。我想这里唯一需要做的是,在运行zlibpush命令之前,我必须检查文件是否被gzip压缩,但我想这相对比较容易。如果有像zcat-f这样的东西可以在gzip或unzip文件上工作,那就太好了,但这是次要的。谢谢接下来,当使用catch{}来捕捉使用zcat{}产生的错误时,它看起来像是Tcl中的head在功能上工作以生成正确的结果,它显然让僵尸进程在服务器上打开,在我的例子中,由于无法创建新进程,导致其他进程出错的可用进程句柄饱和。因此,减少学习,不要走捷径,用正确的方式做事。使用上面推荐的代码也可以解决这个问题。