2017-09-29 1 views
1

Ich versuche, eine HTML-Datei zu analysieren, und ich habe einen regulären Ausdruck, der Muster in allen p-Tags erfasst. Aus irgendeinem Grund wird nur die erste gefundene Instanz gedruckt.Perl: Regex druckt nur das erste gefundene Muster

my @newH2Array = ("Part I", "Part II", "Part III"); 
my $linenumber = 0; 
while (my $line = <$parser>){ 
    chomp $line; 
    $linenumber++; 
    if($line =~ /^<p>/){ 
     if($line =~ /(Part [IVX]+)/gi) { 
      if (grep{ lc $_ eq lc $1 } @newH2Array){ 
       print "found a hit <" . $1 . "> that matches array element on line" . $linenumber; 
      } 
     } 
    } 
} 

Wenn ich laufe es mit diesem Test unten, es würde nur Teil I ausdrucken, aber nicht die anderen 3. Wenn ich wechsle die if-Anweisungen zu einer while-Schleife nicht als entweder nicht funktionieren. Kann mir jemand sagen, was ich hier falsch mache?

<p>Part I should be found. Part II should be found also. Part III should be found.</p> 

Das Ergebnis sollte sein.

found a hit <Part I> that matches array element on line 1 
found a hit <Part II> that matches array element on line 1 
found a hit <Part III> that matches array element on line 1 
+1

Gibt es einen Grund, warum Sie keinen HTML-Parser verwenden? [Zu Ihrem eigenen Vorteil sollten Sie XML nicht mit regulären Ausdrücken analysieren] (https://stackoverflow.com/q/1732348/1331451). – simbabque

+1

weil ich eine Menge Bearbeitungen mache und ich eigentlich das Eric

+0

Es sollte es nicht lesen müssen, sobald Sie damit fertig sind, nur am Anfang, wenn es mehr oder weniger gültige HTML ist. Das bedeutet nicht, dass Sie gültiges HTML als Ausgabe produzieren müssen. – Aaron

Antwort

3

Eine if Anweisung ist eine binäre Wahl. Es passt entweder oder nicht. Für eine Schleife benötigen Sie ein Schleifenkonstrukt - wie while.

Ich habe auch say() statt print(), Perl eingebauten in $. statt $linenumber und ich habe Variablen in Strings interpoliert.

Oh, und wechselte zu <DATA>, um es einfach zu testen.

#!/usr/bin/perl 

use strict; 
use warnings; 
use feature 'say'; 

my @newH2Array = ("Part I", "Part II", "Part III"); 
my $linenumber = 0; 
while (my $line = <DATA>){ 
    chomp $line; 
    if ($line =~ /^<p>/){ 
     while ($line =~ /(Part [IVX]+)/gi) { 
      if (grep{ lc $_ eq lc $1 } @newH2Array){ 
       say "found a hit <$1> that matches array element on line $."; 
      } 
     } 
    } 
} 

__DATA__ 
<p>Part I should be found. Part II should be found also. Part III should be found.</p> 
+0

So lustig, wie unsere Antworten wieder fast identisch sind. So viel zu TIMTOWTDI. :) – simbabque

+1

@simbabque: "Großartige Köpfe denken gleich" oder vielleicht "Narren unterscheiden sich selten" :-) –

+0

okay, also kopiere ich und steckte deinen Code in ein neues pl Skript um es zu testen und es funktioniert perfekt. Wenn ich es durch meine Regex ersetze, beginnt es zu versagen. also denke ich, mein Problem ist mit der Regex. auch danke für mich über Perl in $ gebaut zu wissen. Ich habe diese Woche begonnen, Perl und Regex zu lernen, also gibt es noch viel zu lernen. – Eric

2

Sie verwenden einen /g Spiel, aber Sie sind nur das erste seiner Matches wegen der if nehmen. Sie müssen alle Übereinstimmungen wiederholen. Ein Weg, dies zu tun ist mit einer while Schleife.

my @newH2Array = ("Part I", "Part II", "Part III", "Part X"); 

while (my $line = <DATA>){ 
    chomp $line; 

    if($line =~ /^<p>/){ 
     while ($line =~ /(Part [IVX]+)/gi) { 
      if (grep{ lc $_ eq lc $1 } @newH2Array){ 
       print "found a hit <$1> that matches array element on line $.\n"; 
      } 
     } 
    } 
} 

__DATA__ 
<p>Part I should be found. Part II should be found also. Part III should be found.</p> 
<p>Part X should be found. Particles are fun.</p> 

Beachten Sie, dass ich $linenumber entfernt habe. Sie können einfach $. verwenden, was immer die aktuelle Zeilennummer des zuletzt gelesenen Dateihandles ist.

Hier ist der Ausgang.

found a hit <Part I> that matches array element on line 1 
found a hit <Part II> that matches array element on line 1 
found a hit <Part III> that matches array element on line 1 
found a hit <Part X> that matches array element on line 2 
Verwandte Themen