2017-08-06 2 views
0

Je dois extraire certaines valeurs de chaîne d'un fichier texte à partir des n premières lignes (environ 50 lignes). Dans certains cas, les fichiers sont gzippés et dans certains cas ils ne le sont pas.ne traite que les n premières lignes d'un fichier gzippé en Tcl

actuellement, j'utilise ce qui suit pour lire le fichier, mais cela lit le fichier entier et est lent à traiter de très gros fichiers. Si le fichier n'est pas gzippé, alors cela semble fonctionner correctement et semble assez rapide. Mais quand il est gzippé, je n'arrive pas à zapper juste les n premiers rangs. Je l'ai essayé, mais je reçois une erreur au 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 

Je peux juste essayer d'attraper l'erreur et passer à autre chose, car il ne semble pousser les données dans la variable de données $, mais je me demande si je fais quelque chose d'illégal ici.

Sinon, y a-t-il un moyen pur de Tcl pour accomplir ceci?

Répondre

1

L'erreur vient de close et est parce que zcat a été arrêté (par un signal, SIGPIPE) avant qu'il avait écrit toutes les lignes out. C'est prévu, et vous pouvez l'ignorer et l'ignorer. Mettez le catch autour du close.


En Tcl 8.6 (mais pas une version antérieure, ni dans le paquet zlib autonome pour Tcl, ce qui était fonctionnalité, nous avons ajouté lorsque nous avons importé le paquet dans Tcl), vous pouvez le faire dans le plus pur 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 

La commande zlib fournit une compression et une décompression; zlib push est utilisé pour ajouter en compression ou décompression à un canal, comme dans ce cas où le filtre de canal gunzip a été appliqué.

+0

Merci, vous êtes une richesse de connaissances Tcl. C'est incroyablement rapide. Cela fonctionne réellement plus vite que la commande principale. Je suppose que la seule chose ici est que je dois vérifier si le fichier est gzippé ou non avant d'exécuter la commande zlib push, mais je suppose que c'est relativement facile. Ce serait bien s'il y avait quelque chose comme zcat -f qui fonctionne sur les fichiers gzippés ou non compressés, mais c'est mineur. Merci! – Jonjilla

+0

comme une suite à cela, il semble tout en utilisant catch {} pour attraper l'erreur d'utiliser zcat | head fonctionne fonctionnellement dans Tcl pour générer les bons résultats, il laisse apparemment les processus zombies ouverts sur le serveur et dans mon cas, saturé les handles de processus disponibles qui ont causé d'autres processus à l'erreur en raison de l'incapacité de créer de nouveaux processus. Alors, apprenez moins, ne prenez pas de raccourcis et faites les choses comme il faut. En utilisant le code ci-dessus, vous avez recommandé de résoudre ce problème aussi. – Jonjilla