2017-08-06 115 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

相關問題