2010-11-24 41 views
1

J'ai un fichier texte qui ressemble à ce qui suit:Perl - Commencez à lire de la ligne spécifique et seulement obtenir la première colonne de celui-ci la ligne, jusqu'à la fin

Line 1 
Line 2 
Line 3 
Line 4 
Line 5 
filename2.tif;Smpl/Pix & Bits/Smpl are missing. 

Il y a 5 lignes qui sont toujours les mêmes, et sur la ligne 6 est où je veux commencer à lire des données. Lors de la lecture des données, chaque ligne (à partir de la ligne 6) est délimitée par des points-virgules. Je dois juste obtenir la première entrée de chaque ligne (à partir de la ligne 6).

Par exemple:

Line 1 
Line 2 
Line 3 
Line 4 
Line 5 
filename2.tif;Smpl/Pix & Bits/Smpl are missing. 
filename4.tif;Smpl/Pix & Bits/Smpl are missing. 
filename6.tif;Smpl/Pix & Bits/Smpl are missing. 
filename8.tif;Smpl/Pix & Bits/Smpl are missing. 

sortie souhaitée serait la suivante:

filename2.tif 
filename4.tif 
filename6.tif 
filename8.tif 

Est-ce possible, et si oui, où dois-je commencer?

+1

Il est possible. Avez-vous du code pour le moment? – aschepler

+0

Oui et non. Pas encore pour le moment - mais j'ai plus de 300 lignes de code que j'essaie de mettre en œuvre. Il s'agit essentiellement d'une nouvelle fonctionnalité que j'essaie d'implémenter pour traiter les fichiers à partir d'un fichier texte existant. – drewrockshard

+0

La réponse à toutes les questions commençant, * "En Perl, ¿puis-je faire ...?" * Est ** "¡Oui!" ** Cependant, la réponse à certains d'entre eux continue avec ** "Oui, mais ...." ** – tchrist

Répondre

4

Il utilise le Perl 'autosplit' (ou 'awk') Mode:

perl -n -F'/;/' -a -e 'next if $. <= 5; print "$F[0]\n";' < data.file 

Voir 'perlrun' et 'perlvar'.


Si vous avez besoin de faire cela dans une fonction qui est donnée un descripteur de fichier et un certain nombre de lignes à sauter, alors vous ne serez pas en utilisant le mode « autosplit » Perl.

sub skip_N_lines_read_column_1 
{ 
    my($fh, $N) = @_; 
    my $i = 0; 
    my @files =(); 
    while (my $line = <$fh>) 
    { 
     next if $i++ < $N; 
     my($file) = split /;/, $line; 
     push @files, $file; 
    } 
    return @files; 
} 

Ceci initialise une boucle, lit les lignes, en sautant la première N d'entre eux, puis diviser la ligne de capture et seul le premier résultat. Cette ligne avec my($file) = split... est subtile; les parenthèses signifient que la division a un contexte de liste, ainsi elle génère une liste de valeurs (plutôt qu'un nombre de valeurs) et assigne la première à la variable. Si les parenthèses étaient omises, vous fourniriez un contexte scalaire à un opérateur de liste, afin que vous obteniez le nombre de champs dans la sortie fractionnée affectée à $file - pas ce dont vous aviez besoin. Le nom du fichier est ajouté à la fin du tableau et le tableau est renvoyé. Puisque le code n'a pas ouvert le handle de fichier, il ne le ferme pas. Une interface alternative passerait le nom du fichier (au lieu d'un handle de fichier ouvert) dans la fonction. Vous devez ensuite ouvrir et fermer le fichier dans la fonction, en vous souciant de la gestion des erreurs.

Et si vous avez besoin de l'aide à l'ouverture du fichier, etc, puis:

use Carp; 

sub open_skip_read 
{ 
    my($name) = @_; 
    open my $fh, '<', $name or croak "Failed to open file $name ($!)"; 
    my @list = skip_N_lines_read_column_1($fh, 5); 
    close $fh or croak "Failed to close file $name ($!)"; 
    return @list; 
} 
+0

+1. Meilleure réponse, vraiment. Je dois sauver la partie perl de mon cerveau :) –

+0

Comment est-ce que j'écrirais ceci dans un script, et pas dans une ligne de commande, et lirais d'un gestionnaire de fichier ouvert d'un fichier qui existe déjà? – drewrockshard

+0

@Jonathan: Cela me fait peur que perl sache gober vos délimiteurs slash autour du séparateur. Je ne savais pas que c'était ça! – tchrist

2

Assez moche mais, lire les lignes fictives et ensuite diviser; pour le reste d'entre eux.

my $logfile = '/path/to/logfile.txt'; 

open(FILE, $logfile) || die "Couldn't open $logfile: $!\n"; 

for (my $i = 0 ; $i < 5 ; $i++) { 
    my $dummy = <FILE>; 
} 

while (<FILE>) { 
    my (@fields) = split /;/; 
    print $fields[0], "\n"; 
} 

close(FILE); 
+0

Cela peut s'écrire quelque chose comme: 'my @dummy; @dummy [0..4] = ; map {($ a) = diviser /; /; imprimer $ a, "\ n"} ; '. –

+0

Que faire si j'essaie de lire à partir d'un fichier, mais pas à partir de la ligne de commande. J'ai un fichier qui est dans un emplacement relatif (donc je peux l'appeler par logfile.txt, par exemple). J'ai du mal à le lire, jusqu'à présent, mon code tourne continuellement en boucle et je dois en sortir CTRL + C. – drewrockshard

+1

@Diego: * Par desgracia, * cela ne marchera pas parce que vous venez de fournir le contexte de la liste à l'opérateur 'readline' dans votre affectation de tranche, épuisant ainsi l'entrée. Les lignes restantes ont été jetées. – tchrist

2
#!/usr/bin/env perl 
# 
# name_of_program - what the program does as brief one-liner 
# 
# Your Name <[email protected]_host.TLA> 
# Date program written/released 
################################################################# 

use 5.10.0; 

use utf8; 
use strict; 
use autodie; 
use warnings FATAL => "all"; 

# ⚠ change to agree with your input: ↓ 
use open ":std" => IN => ":encoding(ISO-8859-1)", 
        OUT => ":utf8"; 
# ⚠ change for your output: ↑ — *maybe*, but leaving as UTF-8 is sometimes better 

END {close STDOUT} 

our $VERSION = 1.0; 

$| = 1; 

if (@ARGV == 0 && -t STDIN) { 
    warn "reading stdin from keyboard for want of file args or pipe"; 
} 

while (<>) { 
    next if 1 .. 5; 
    my $initial_field = /^([^;]+)/ ? $1 : next; 
    # ╔═══════════════════════════╗ 
    # ☞ your processing goes here ☜ 
    # ╚═══════════════════════════╝ 
} continue { 
    close ARGV if eof; 
} 

__END__ 
+0

Les gars, je suis toujours perdu - ** nouveau à Perl **. J'ai déjà un fichier qui contient tout. J'ai juste besoin d'ouvrir le fichier dans mon script, sauter les 5 premières lignes, et sortir la première colonne de chaque ligne après la 5ème ligne. – drewrockshard

+0

@drewsrockhard: C'est ce que fait mon programme. Essaye le. – tchrist

+0

Pouvez-vous montrer un exemple sur comment l'exécuter et où placer votre "fichier d'entrée"? – drewrockshard