2013-09-07 19 views
6

Ho un grande file di testo (300 kB) contenente parole delimitate da spazi. Ora voglio aprire questo file ed elaborare ogni parola in esso uno per uno.Leggi il file di testo in Perl parola per parola anziché riga per riga

Il problema è che perl legge il file riga per riga (cioè l'intero file in una sola volta, il che mi dà strani risultati. So che il modo normale è quello di fare qualcosa di simile

open($inFile, 'tagged.txt') or die $!; 
$_ = <$inFile>; 
@splitted = split(' ',$_); 
print $#splitted; 

Ma questo mi dà un conteggio delle parole difettosa (troppo grande array?).

È possibile leggere il file di testo parola per parola, invece?

+4

Cosa intendi contano una parola "guasto" leggermente modificata? Inoltre, se vuoi il numero di elementi in '@ diviso ', usa' scalare @ diviso'. Infine, il codice che hai sta leggendo solo una riga del file. –

+0

@AndyLester. Quando ho detto che le parole erano delimitate da spazi intendevo per spazi e solo per spazi. Quindi il codice sopra legge l'intero file in un colpo solo. Scusa se non era chiaro.Quando ho eseguito wc sul file, ho ottenuto un conteggio delle parole di 41404, quando ho eseguito il codice sopra ho ottenuto un conteggio delle parole del 1948 e quando ho provato la soluzione di RobEarl ho ottenuto nuovamente 41404. –

+0

Immagino che ci siano delle nuove righe nel file di cui non si è a conoscenza; non c'è altro motivo per cui il tuo codice non dovrebbe funzionare così com'è. Cosa dice 'wc' per il numero di righe nel file (il primo numero nell'output)? – Borodin

risposta

4

Per leggere un file parola alla volta, modificare il separatore di record in ingresso ($/) ad uno spazio:

local $/ = ' '; 

Esempio:

#!/usr/bin/perl 
use strict; 
use warnings; 

use feature 'say'; 

{ 
    local $/ = ' '; 

    while (<DATA>) { 
     say; 
    } 
} 

__DATA__ 
one two three four five 

uscita:

one 
two 
three 
four 
five 
+0

Non è necessario eseguire questa operazione per un file da 300 KB e non considera la possibilità di più spazi tra le parole. – Borodin

+1

Ciao, questo sembra non funzionare per linee multiple. L'ultima parola nella prima riga e la prima nella seconda riga verranno lette come una parola. 'one due tre quattro cinque uno due tre quattro cinque' Qualche soluzione a questo problema? Grazie. – stenlytw

5

Invece di leggerlo in un colpo solo, provare l'approccio linea per linea che è più facile anche sull'utilizzo della memoria della macchina (anche se 300 KB non è troppo grande per i computer moderni).

use strict; 
use warnings; 

my @words; 
open (my $inFile, '<', 'tagged.txt') or die $!; 

while (<$inFile>) { 
    chomp; 
    @words = split(' '); 
    foreach my $word (@words) { # process } 
} 

close ($inFile); 
2

Non è chiaro cosa siete Sembra che il file di input sia simile, ma implica che contenga solo una singola riga composta da molte "parole".

300KB è lontano da un "file di testo grande". Dovresti leggerlo nella sua interezza e tirare le parole da lì a uno a uno. Questo programma dimostra

use strict; 
use warnings; 

my $data = do { 
    open my $fh, '<', 'data.txt' or die $!; 
    local $/; 
    <$fh>; 
}; 

my $count = 0; 
while ($data =~ /(\S+)/g) { 
    my $word = $1; 
    ++$count; 
    printf "%2d: %s\n", $count, $word; 
} 

uscita

1: alpha 
2: beta 
3: gamma 
4: delta 
5: epsilon 

Senza ulteriori spiegazioni di ciò che un "conteggio delle parole difettosa" potrebbe essere che è molto difficile da aiutare, ma è certo che il problema ISN a causa della dimensione dell'array: se ci fosse un problema allora Perl avrebbe sollevato un'eccezione e sarebbe morta.

Ma se si sta confrontando il risultato con le statistiche da un elaboratore di testi, allora è probabilmente perché la definizione di "" parola " è diversa. Ad esempio, il word processor può considerare una parola sillabata come due parole.

1

300K non sembra essere grande, quindi si può provare:

my $text=`cat t.txt` or die $!; 
my @words = split /\s+/, $text; 
foreach my $word (@words) { # process } 

o una soluzione di squiguy

use strict; 
use warnings; 

my @words; 
open (my $inFile, '<', 'tagged.txt') or die $!; 

while (<$inFile>) { 
    push(@words,split /\s+/); 
} 
close ($inFile); 
foreach my $word (@words) { # process } 
Problemi correlati