2013-09-07 20 views
6

Ich habe eine große (300 kB) Textdatei, die durch Leerzeichen begrenzte Wörter enthält. Jetzt möchte ich diese Datei öffnen und jedes Wort einzeln verarbeiten.Textdatei in Perl Wort für Wort statt Zeile für Zeile lesen

Das Problem ist, dass Perl liest die Datei Zeile für Zeile (d. H.) Die gesamte Datei auf einmal, die mir seltsame Ergebnisse gibt. Ich weiß, der normale Weg ist, etwas zu tun wie

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

Aber das gibt mir eine fehlerhafte Wortzahl (zu große Array?).

Ist es möglich, die Textdatei Wort für Wort zu lesen?

+4

Was meinst du ein "fehlerhaft" Wort zählen? Wenn Sie die Anzahl der Elemente in '@ splitted' haben wollen, verwenden Sie' scalar @ splitted'. Schließlich liest der Code, den Sie haben, nur eine Zeile der Datei. –

+0

@AndyLester. Als ich sagte, dass die Wörter durch Leerzeichen begrenzt waren, meinte ich mit Leerzeichen und nur mit Leerzeichen. Der obige Code liest also die gesamte Datei auf einen Schlag. Entschuldigung, wenn das unklar war.Wenn ich wc auf der Datei lief, bekam ich eine Wortzahl von 41404, als ich den obigen Code ausführte, bekam ich eine Wortzahl von 1948, und als ich RobEarls Lösung ausprobierte, bekam ich 41404 wieder. –

+0

Ich kann mir vorstellen, dass es neue Zeilen in der Datei gibt, die Ihnen nicht bekannt sind. Es gibt keinen anderen Grund, warum Ihr Code nicht so funktionieren sollte, wie er ist. Was sagt "wc" für die Anzahl der Zeilen in der Datei (die erste Zahl in der Ausgabe)? – Borodin

Antwort

4

Um die Datei zu einem Wort zu einem Zeitpunkt zu lesen, zu einem Raum, den Eingabedatensatz-Trenn ($/) ändern:

local $/ = ' '; 

Beispiel:

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

use feature 'say'; 

{ 
    local $/ = ' '; 

    while (<DATA>) { 
     say; 
    } 
} 

__DATA__ 
one two three four five 

Output:

one 
two 
three 
four 
five 
+0

Es gibt keine Notwendigkeit, dies für eine 300 KB-Datei zu tun, und es berücksichtigt nicht die Möglichkeit von mehreren Leerzeichen zwischen Wörtern. – Borodin

+1

Hi, das scheint nicht für mehrere Zeilen zu funktionieren. Das letzte Wort in der ersten Zeile und das erste Wort in der zweiten Zeile werden als ein Wort gelesen. 'eins zwei drei vier fünf ein zwei drei vier fünf' Irgendeine Lösung für dieses Problem? Vielen Dank. – stenlytw

5

Anstatt es auf einen Schlag zu lesen, versuchen Sie es mit der Zeile-für-Zeile-Methode, die die Speicherauslastung Ihrer Maschine ebenfalls erleichtert (obwohl 300 KB für moderne Computer nicht zu groß ist).

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

Es ist unklar, was yo Eine Eingabedatei sieht so aus, aber Sie meinen, dass sie nur eine einzige Zeile enthält, die aus vielen "Wörtern" besteht.

300 KB ist weit entfernt von einer "große Textdatei". Sie sollten es in seiner Gesamtheit lesen und die Wörter von dort eins nach dem anderen ziehen. Dieses Programm demonstriert

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; 
} 

Ausgang

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

Ohne weitere Erklärung, was ein „fehlerhafte Wortzahl“ könnte sein, es ist sehr schwer zu helfen, aber es ist sicher, dass das Problem isn t wegen der Größe deines Arrays: Wenn dort ein Problem war, würde Perl eine Ausnahme auslösen und sterben.

Aber wenn Sie das Ergebnis mit der Statistik von einem Textverarbeitungsprogramm vergleichen, dann ist es wahrscheinlich, weil die Definition von "Wort" ist anders. Zum Beispiel kann das Textverarbeitungsprogramm ein Wort mit Bindestrich als zwei Wörter betrachten.

1

300K scheint nicht groß zu sein, so können Sie versuchen:

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

oder leicht modifizierte Lösung von 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 } 
Verwandte Themen