2009-06-15 10 views
3

Ich lese jede Zeile einer Eingabedatei (IN) und drucke die gelesene Zeile in eine Ausgabedatei (OUT), wenn die Zeile mit einem der Muster beginnt, sagen wir "ab", "cd", "ef", " gh "," ij "usw. Die gedruckte Zeile hat die Form" Muster: 100 "oder Form" Muster: 100: 200 ". Ich muss "Muster" durch "myPattern" ersetzen, d. H. Die aktuelle Zeile in FILE drucken, aber den gesamten Text vor dem ersten Vorkommen von ":" durch "myPattern" ersetzen. Was ist der beste Weg, dies zu tun?Wie kann ich den gesamten Text vor der Übereinstimmung in einer Perl-Ersetzung ersetzen?

Zur Zeit habe ich:

while (<IN>) 
{ 
    print FILE if /^ab:|^bc:|^ef:|^gh:/; 
} 

Ich bin nicht sicher, wenn substr Ersatz als „Muster“ helfen würde, kann entweder „ab“ oder „CD“ oder „ef“ oder „gh“ usw.

sein

Danke! Bi

+0

Können Sie ein Beispiel geben, wie das Vorher und Nachher aussieht? – YGA

+1

Beispiel OUTPUT: VOR Mittelwert: 100 NACH Variance: 100 ODER VOR Kanaldaten: 50 NACH Kanal Frequenz: 50 Dank! –

Antwort

0
sub replacer { 

    $line = shift; 
    $find = shift; 
    $replace = shift; 

    $line =~ /([^:]+):/ 
    if ($1 =~ /$find/) { 
     $line =~ s/([^:]+):/$replace/ ; 
     return $line;  
    } 
    return ; 

} 

while (<IN>) 
{ 
    print OUT replacer ($_,"mean","variance"); 
    print OUT replacer ($_,"pattern","newPattern"); 
} 

Meine Perl ein wenig rostig ist, so Syntax möglicherweise nicht genau sein.

bearbeiten: Setzen Sie es in eine Funktion für Sie.

+0

Danke Byron - Dies ist, was ich brauche, da der Wert von "myPattern" basierend auf dem Wert in "Muster", d. H. "Ab" oder "cd" oder "ef" variiert. Kann ich das als Einzeiler machen? –

+0

$ line = ~/([^:] +):/ Was bedeutet der Doppelpunkt? Vielen Dank. –

+0

[^:] + - bedeutet alles, was nicht mit einem Doppelpunkt übereinstimmt. –

0
while (<IN>) 
{ 
    s/^pattern:/myPattern:/; 
    print OUT 
} 
+0

Damit wird jede Zeile unabhängig davon gedruckt, ob sie mit dem Muster übereinstimmt. Wenn ich die ursprüngliche Frage lese, sollten nur übereinstimmende Zeilen transformiert und nach OUT geschrieben werden. –

1

Perl Substitution Operator standardmäßig (a) verwendet das erste Spiel, (b) ersetzt nur ein Spiel und (c) liefert true, wenn ein Ersatz gemacht und falsch, wenn es nicht ist.

So:

while (<IN>) 
{ 
    if (s/<pattern1>:/<replace1>/ || 
     s/<pattern2>:/<replace2>/) { 
     print FILE; 
    } 
} 

Sollte für Sie arbeiten. Beachten Sie, dass aufgrund von Kurzschlüssen nur eine Ersetzung vorgenommen wird.

+0

Beachten Sie, dass Sie mit dieser Substitution auch den ersten Doppelpunkt entfernen. –

+0

nicht, wenn replace1 und replace2 auch Doppelpunkte haben – YGA

0

Dies könnte das sein, was Sie wollen:

$expr = "^(ab)|(cd)|(ef)|(gh)|(ij)"; 
while (<IN>) 
{ 
    if (/$expr:/) 
    { 
     s/$expr/$myPattern/; 
     print FILE; 
    } 
} 
0

Der kürzeste Weg, um das zu tun, was Sie oben fragen, besteht darin, Ihren Code wiederzuverwenden, aber eine Ersetzung einzuschließen.

while (<IN>) 
{ 
    print FILE if s/^(ab|bc|ef|gh):/MyPattern:/; 
} 

Alle Muster auf der linken Seite werden ersetzt. Wenn die linke Seite nicht übereinstimmt, wird nichts gedruckt.

3

generisch, tun dies wie:

my %subst = ('ab' => 'newab', 'bc' => 'newbc', 'xy' => 'newxy'); 
my $regex = join('|', map quotemeta, sort { length($b) <=> length($a) } keys %subst); 
$regex = qr/^($regex):/; 

while (<IN>) { 
    print FILE if s/$regex/$subst{$1}:/; 
} 

Die Art stellt die längsten erste, so dass, wenn die Daten ab hat :: und beide ab und ab: substituiert werden, ab: wird verwendet, statt ab.

Verwandte Themen