2017-08-06 17 views
0

トップn行(約50行)からテキストファイルからいくつかの文字列値を抽出する必要があります。場合によっては、ファイルはgzipされており、場合によってはそうではありません。Tclのgzippedファイルのトップn行だけを処理する

現在、私はファイルを読むために使用していますが、これはファイル全体を読み取り、非常に大きなファイルを処理するのが遅いです。

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

ファイルがgzipでない場合は、これは正常に動作しているように見えますが、かなり高速です。

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

しかし、gzipされていると、トップn行だけをzcatすることはできません。私はこれを試してみたが、私は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それを無視することができます。 closeのまわりにcatchを置きます。 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チャネルフィルタが適用されています)。

+0

ありがとうございます、あなたはTclの知識の富です。これは信じられないほど高速です。実際にはheadコマンドよりも速く動作します。ここで唯一のことは、zlib pushコマンドを実行する前にファイルがgzipされているかどうかを確認する必要があることですが、それは比較的簡単だと思います。 gzipやungzippedのどちらのファイルでも動作するzcat -fのようなものがあればいいですが、それは軽微です。ありがとう! – Jonjilla

+0

これをフォローアップすると、catch {}を使用してzcatを使用してエラーを捕捉しているように見えます。 Tcl内で機能的に機能して正しい結果を生成すると、ゾンビプロセスがサーバ上にオープンしていて、私のケースでは利用可能なプロセスハンドルが飽和してしまい、新しいプロセスを作成できないために他のプロセスがエラーになります。だから、学んだことはありません、ショートカットを取って、正しいことをやってはいけません。上記のコードを使用することで、その問題も解決することをお勧めします。 – Jonjilla

関連する問題