2 Stimmen

Ein verschachtelter Regulärer Ausdruck passt nicht, wenn er mit dem /g Modifier verwendet wird.

Lassen Sie uns dieses Programm betrachten:

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

my $file = <<END_FILE;
*   Action    : Lorem ipsum
*               Dolor oktam
*               Lorem lorem
*
*   Input     : var1
*               var2
*               var3
*
*   Output    : var4
*               var5
*               var6
END_FILE

$_ = $file;

my ($action, $input) = ('', '');

if (/action\s+:\s*((.|\r\n|\n)*?)(\r\n|\n).*\s*input/gi) {
    say "Action: $1";
}

# Nichts erfassen
if (/input\s+:\s*((.|\r\n|\n)*?)(\r\n|\n).*\s*output/gi) {
    say "Input: $1";
}

# Aber dieses Mal funktioniert es
if ($file =~ /input\s+:\s*((.|\r\n|\n)*?)(\r\n|\n).*\s*output/gi) {
    say "Input OK: $1";
}

# Und $_ unterscheidet sich nicht von $file
die "WTF!" unless $_ eq $file;

Ich möchte Informationen nach "Action", "Input" und "Output" extrahieren. Das Seltsame passiert, wenn ich versuche, die Informationen nach "Input" zu erhalten. Wenn ich $_ verwende, stimmt der Regex nichts überein, aber es funktioniert, wenn ich $file verwende, obwohl $_ eq $file

Woher kommt mein Problem?

Die Ausgabe, die ich erhalte, ist diese:

Action: Lorem ipsum
*               Dolor oktam
*               Lorem lorem
*
Input OK: var1
*               var2
*               var3
*

6voto

Qtax Punkte 32095

Dies liegt daran, dass du /g verwendest, das dazu führt, dass das nächste Match versucht, ein Match nach dem Ende des letzten Matches zu finden. Da das erste Match input verbraucht, wird das zweite nach input starten und somit nie ein weiteres input finden, um zu matchen.

Du kannst /g entfernen, um das zu lösen.

perlop wird dir sagen, dass:

Der /g Modifier spezifiziert globales Muster-Matching, d.h. so oft wie möglich innerhalb des Strings zu matchen. Wie es sich verhält, hängt vom Kontext ab. Im Listen-Kontext gibt es eine Liste der Teilstrings zurück, die von jeglichen erfassenden Klammern im regulären Ausdruck gematcht wurden. Wenn es keine Klammern gibt, gibt es eine Liste aller gematchten Strings zurück, so als ob es Klammern um das gesamte Muster gäbe.

Im skalaren Kontext findet jede Ausführung von m//g das nächste Match, gibt true zurück, wenn es matched, und false, wenn kein weiteres Match mehr gibt. Die Position nach dem letzten Match kann mit der pos() Funktion gelesen oder gesetzt werden; siehe pos. Ein fehlgeschlagenes Match setzt normalerweise die Suchposition zurück zum Anfang des Strings, aber du kannst das vermeiden, indem du den /c Modifier hinzufügst (z.B. m//gc). Das Modifizieren des Zielstrings setzt auch die Suchposition zurück.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X