2016-07-25 9 views
0

Gibt es eine bessere Möglichkeit, doppelte Zeichenketten aus einer Datei in Perl zu ziehen?

Ich bin derzeit durch eine Protokolldatei looping durch bestimmte Merkmale herausziehen. Ich muss nach einer eindeutigen Zeichenfolge suchen, wenn es dupliziert wird, und wenn die Zeichenfolge dupliziert ist, dann ignoriere dieses Protokoll. Momentan benötigt mein Code eine absurde Menge an Zeit, um zu laufen (oder ich bin in einer Endlosschleife) yippey. Gibt es eine bessere Möglichkeit, Duplikate aus einer Datei zu ziehen und sie auf Eindeutigkeit zu prüfen?

close($handle); 

$test = "testFile.txt"; 

open($handle, '<', $domainAnalysis) or die "Cannot open file: $!"; 
open($hand, '>', $test)   or die "Cannot open file: $!"; 

my %uniq; 

while ($search = <$handle>) { 

    if ($search =~ /Mail ID: ([^:]*)\n/g) { 
     $uniq{$search}++; 
    } 

    my @sortedHash = sort keys %uniq; 

    foreach $i (@sortedHash) { 

     if ($i eq $search) { 
      print $hand $search; 
      print $hand scalar <$handle> for 1 .. 2; 
     } 
    } 
} 

Jede Hilfe würde sehr geschätzt werden. Ich bin irgendwie festgefahren.

Edit:

Es ist derzeit eine Protokolldatei liest und benötigten Informationen in eine neue Datei zu ziehen. Die neue Datei wird in dem Format dieser

Mail ID: b12342534 
Domain : [email protected] 
Status Message = Sent 

Mail ID: a32432234 
Domain : [email protected] 
Status Message = Deferred 

ausgedruckte Ausgabe: Nun, das Programm stoppt nie tatsächlich. Es dauert ewig und meine Geduld wird es nicht den ganzen Weg laufen lassen.

+0

geben Sie bitte Beispiel Eingabe/Ausgabe als auch http://stackoverflow.com/help/ mcve – Sundeep

+0

Ohne Beispieldaten ist es schwer zu beantworten. Aber ich denke, es wird sein, weil deine innere Schleife stetig größer wird und jede Iteration, du sortierst es. – Sobrique

+0

Einige tatsächliche Stichprobendaten sind erforderlich. "so etwas wie" ist nicht genug für uns zu helfen. (Es muss nicht "echte" Daten sein, aber es muss GENAU die richtige Formatierung haben) – Sobrique

Antwort

2

Ich bin mir ziemlich sicher, dass Ihr Problem ist diese innere Schleife - wie Sie das Protokoll iterieren, vermutlich werden Sie eine erhebliche Anzahl von 'Mail ID' Einträge akkumulieren.

Und jede Schleife, Sie sortieren sie alle, und dann iterieren sie alle und vergleichen sie.

Und - noch wichtiger - Ihre $search, die Sie in jeden Hash einfügen, ist EACH LINE, was bedeutet, dass es sehr groß wird.

Wie dem auch sei - ich würde Ihre Eingangsdaten schlagen gegeben, zunächst einmal Sie $/ verwenden:

local $/ = ''; #read in paragraph mode. 
my %seen; 
while (<$input>) { 
    my ($id) = m/Mail ID: ([^:]*)/; 
    print unless $seen{$id}++; 
} 

Und das wird nur das erste Mal eine bestimmte E-Mail-ID drucken wird gesichtet.

(Natürlich, wenn Sie nur Duplikate drucken können Sie ‚wenn‘ statt ‚es sei denn‘ verwenden)

+0

Das funktioniert für mich, danke. – cvirus96

+0

Obwohl, wenn ich das in eine Datei umleiten wollte, wie würde ich das tun? Aus irgendeinem Grund, wenn ich folgendes benutze: print $ handle wenn $ seded {$ id} ++; funktioniert nicht – cvirus96

+0

Um das exakte 'print if ... idiom zu verwenden, müssen Sie' select' verwenden, um die Standardausgabe auszuwählen - z. 'select $ handle;' - außerhalb der Schleife ist in Ordnung. Andernfalls, wenn Sie es explizit tun wollen: 'print {$ handle} $ _ außer $ seen {$ id} ++;' – Sobrique

1

Zunächst muss nicht über alle Schlüssel eines Hashes iteriert werden; es bricht den ganzen Punkt eines Hash

Angenommen, Sie wollten Element $arr[3] von Arra @arr, würden Sie dies schreiben?

for my $i (0 .. $#arr) { 
    if ($i == 3) { 
     print "Found: $arr[$i]\n"; 
    } 
} 

und so können Sie Zugriff auf nur alle zuvor bestehenden Element %uniq mit $uniq{$search}

Zweitens, können Sie einfach testen, ob das Element der %uniq momentan Null ist, wenn Sie es erhöhen

Like this

my $test   = 'testFile.txt'; 
my $domainAnalysis = '...'; 

open my $handle, '<', $domainAnalysis or die qq{Cannot open "$domainAnalysis": $!}; 
open my $hand, '>', $test   or die qq{Cannot open "$test": $!}; 

my %uniq; 

while (my $search = <$handle>) { 

    next unless $search =~ /^Mail ID:/; 

    if ($uniq{$search}++) { 
     print $hand $search; 
     print $hand scalar <$handle> for 1 .. 2; 
    } 
} 

Sie auch muss immeruse strict und use warnings 'all' und alle Ihre Variablen mit my so nahe wie möglich erklären, wo sie verwendet werden, erste

Und $hand und $handle sind schreckliche Namen für Datei-Handles!

+1

Ich vermute, dass es nach eindeutigen Mail-IDs sucht, anstatt eindeutige Zeilen in der Datei. (Ich bin mir aber nicht ganz sicher). Und ebenso - ich nehme an, dass es zwei zusätzliche Zeilen aus der Datei liest, weil es etwas mit einem Datensatz macht, aber ... – Sobrique

+0

@Sobrique: Ich habe nur die vorhandene Funktionalität kopiert. Es ist eine andere Frage, wenn das nicht funktioniert! – Borodin