Dieser lokale $key
geht aus dem Geltungsbereich, sobald if
ist getan und existiert nicht außerhalb des if
Block. Die globale $key
ist wieder verfügbar nach der if
, sichtbar an anderer Stelle in der Schleife, aber ist nicht definiert, da es nie zugewiesen wurde. Das gleiche gilt für $value
im elsif
Block.
Lassen Sie einfach die my
Deklaration innerhalb der Schleife fallen, also diesen globalen Variablen zuweisen (wie vorgesehen?). Also, $key = ...
und $value = ...
, und der Hash wird korrekt zugewiesen.
Hinweis - hier geht es darum, wie Sie diese Hash-Zuweisung richtig erhalten. Ich weiß nicht, wie Ihre tatsächlichen Daten aussehen und ob die Zeile korrekt analysiert wird. Hier ist ein Spielzeug input.txt
@cluster t.1
1111 ../../../output1.1.txt/
@cluster t.2
2222 ../../../output2.2.txt/
Ich nehme das 4. Feld anstatt den 6., $value = $output[3];
, und fügen Sie
print "$_ => $hash{$_}\n" for keys %hash;
nach der Schleife. Diese Drucke
Ich bin nicht sicher, ob das ist, was Sie wollen, aber der Hash ist gut gebaut.
Ein Kommentar über Auswahl von Werkzeugen in
Parsen analysieren Sie die Linien für Zahlen, durch die Eigenschaft split
mit den Separatoren als auch zurückkehren, wenn sie erfasst werden. Das ist ordentlich, aber in gewisser Hinsicht kehrt es seinen Hauptzweck um, nämlich andere Komponenten aus der Zeichenfolge zu extrahieren, wie durch das Muster begrenzt. So kann es den Zweck des Codes ein wenig verschachtelt machen, und Sie müssen auch sehr genau indexieren, um zu erhalten, was Sie brauchen.
Anstatt split
zu verwenden, um das Trennzeichen selbst zu extrahieren, das durch eine Regex gegeben wird, warum nicht es durch eine Regex extrahieren? Das macht die Absicht auch klar.Zum Beispiel mit Eingang
@cluster t.10 has 4319 elements, 0 subclusters
37652 ../../../../clust/output43888.txt 1.397428
kann die Analyse gehen als
if ($line =~ m/^\@cluster/) {
($key) = $line =~ /t\.(\d+)/;
}
elsif ($line =~ m/^(\d+)/) {
($value) = $line =~ m|.*/(\w+\.txt)|;
}
$hash{$key} = $value if defined $key and defined $value;
wo t\.
und \.txt
werden hinzugefügt, um genauer die Ziele angeben. Wenn die Zielzeichenfolgen nicht sicher sind, dass sie genau diese Form haben, erfassen Sie einfach \d+
, und im zweiten Fall alle nicht Leerzeichen nach der letzten /
, sagen wir m|^\d+.*/(\S+)|
. Wir verwenden die Gierigkeit von .*
, die alles möglich ist bis zu der Sache, die danach kommt (a /
), also den ganzen Weg bis zum allerletzten /
.
Dann können Sie auch
if ($line =~ m/^\@cluster\s+t\.(\d+)/) {
$key = $1;
}
elsif ($line =~ m|^\d+.*/(\w+\.txt)|) {
$value = $1;
}
Hinweis zum Beispiel für jede Zeile, auf einen einzigen regulären Ausdruck reduzieren, dass ich eine Bedingung für die Hash-Zuordnung hinzugefügt habe. Der ursprüngliche Code ordnet der ersten Iteration tatsächlich einen undef
zu, da zu diesem Zeitpunkt noch kein $value
gesehen wurde. Dies wird bei der nächsten Iteration überschrieben und wir sehen es nicht, wenn wir den Hash anschließend nur ausdrucken. Die Bedingung schützt Sie auch vor fehlgeschlagenen Übereinstimmungen, vor falsch formatierten Zeilen oder ähnlichem. Natürlich können weitaus bessere Kontrollen durchgeführt werden.
Lassen Sie die 'my' von' my $ key' und 'my $ value' in die' if/elsif' Blöcke fallen, da dies _new_ Variablen erzeugt und die globalen Variablen versteckt. Aber was ist das erwartete Ergebnis? '{1 => 'Ausgabe ###. Txt', 2 => 'Ausgabe ###. Txt'}'? – PerlDuck
@PerlDog Danke für die Rückmeldung. Ja, der Hash, den ich möchte, ist '{1 => 'Ausgabe ###. Txt', 2 => 'Ausgabe ###. Txt'}' - Ich würde einfach einen Zähler hinzufügen, aber die Zahlen sind nicht drin Bestellung in meiner Eingabedatei. – EA00
Ok, und wie bezieht sich die "1" in Zeile 1 auf die "1111" in Zeile 2? Warum passen sie zusammen? Weil die 2. Zeile mit 4 mal der Nummer von Zeile 1 beginnt oder weil es 'number + 1110' ist? Oder einfach, weil es die nächste Zeile ist? Bitte zeigen Sie einige Eingaben an, die nicht mehrdeutig sind. – PerlDuck