2017-08-06 145 views
0

我需要从前n行(大约50行)中的文本文件中提取一些字符串值。在某些情况下,这些文件会被压缩,在某些情况下它们不会。只处理Tcl中gzip文件的前n行

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

set f [open "| zcat -f $filename" r] 

如果文件没有被压缩,那么这似乎工作正常,似乎很快。

set f [open "| head -n 50 $filename" r] 

但是当它被gzipped,我似乎无法zcat只是前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 

我只能尝试捕获错误并继续前进,因为它似乎将数据推入$数据变量,但我想知道如果我在这里做一些非法的事情。

另外,是否有一个纯粹的Tcl方式来实现这一点?

回答

1

错误来自close,并且是因为zcat在写入所有行之前已停止(通过信号SIGPIPE)。这是预期的,你可以安全地catch它并忽略它。把catch围绕close


在Tcl的8.6(而不是以前的版本,也没有在自由站立的zlib包的Tcl,这是当我们进口包入的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通道过滤器的情况下。

+0

谢谢,你是丰富的Tcl知识。这非常快。它实际上比头部命令更快。我想这里唯一的问题是我必须在运行zlib push命令之前检查文件是否被gzip压缩,但我想这相对容易。如果有类似zcat -f的文件可以在gzip文件或unzip文件上运行,那会很好,但这很不重要。谢谢! – Jonjilla

+0

作为这个的后续,它看起来像使用catch {}捕获错误从使用zcat |头部在Tcl内部起作用以产生正确的结果,它显然使僵尸进程在服务器上打开,在我的情况下,饱和了可用的进程句柄,这导致其他进程由于无法创建新进程而出错。所以减少学习,不要走捷径,以正确的方式做事。使用你推荐的上述代码也可以解决这个问题。 – Jonjilla