2016-12-02 2 views
0

Ich möchte die Situation mit regulärem Ausdruck in Perl verstehen.Warum bricht ein Wort die richtige Ausgabe in Regex (Perl)?

$str = "123-abc 23-rr"; 

Sie müssen beide Wörter neben Minus anzeigen. Regulärer Ausdruck ist:

@mas=$str=~/(?:([\d\w]+)\-([\d\w]+))/gx; 

Und es richtig Ausgabe zeigen: 123, abc, 23, rr. Aber wenn ich Zeichenfolge ein wenig und legte ein Wort in Start ändern:

$str = "word 123-abc 23-rr"; 

Und ich möchte, nehmen Sie dieses erste Wort-Konto, so dass ich meine regexp ändern:

@mas=$str=~/\w+\s(?:\s*([\d\w]+)\-([\d\w]+))*/gx; 

Mein Ausgang muss gleich sein , aber es gibt: 23, rr. Wenn ich \s* oder * entferne, ist der Ausgang 123, abc. Aber es ist immer noch nicht richtig. Wer weiß warum?

+1

Sie können über lesen * Erfassung wiederholten Gruppen * [hier] (http://www.regular-expressions.info/captureall.html) –

+0

Wenn Sie einen bestimmten Anfang Eingabezeichenfolge angeben, können Sie nicht Tell Engine, um eine 'globale' Übereinstimmung für einen Teil der Regex zu erstellen. – revo

+0

Siehe auch [Wiederholte Erfassung und Analyse] (http://blogs.perl.org/users/sirhc/2012/05/repeated-capturing-and-parsing.html). Beachten Sie, dass es nicht das erste '\ w +' ist, das der "Täter" ist, sondern der '*' Quantifizierer, den Sie in der nicht-einfangenden Gruppe gesetzt haben. –

Antwort

1

Anstatt einen immer spezifischeren Regex für eine immer spezifischere Saite zu erstellen, sollten Sie das Gesamtmuster ausnutzen.

  1. Jedes Stück ist durch Leerzeichen getrennt.
  2. Das erste Stück ist ein Wort.
  3. Der Rest sind Paare, die durch Bindestriche getrennt sind.

Zuerst teilen Sie die Stücke auf Whitespace.

my @pieces = split /\s+/, $str; 

Dann entfernen Sie das erste Stück, es muss nicht gespalten werden.

my $word = shift @pieces; 

gespalten Dann wird jedes Stück auf - in Paare.

my %pairs = map { split /-/, $_ } @words; 
+0

Ok, Sie bevorzugen einen anderen Ansatz, sehr interessant. Ich werde es versuchen – Log

1

Für jede Übereinstimmung wird jede Erfassung zurückgegeben.


Im ersten Snippet stimmt das Muster zweimal überein.

123-abc 23-rr 
\_____/ \___/ 

Es gibt zwei Aufnahmen, so vier (2 * 2 = 4) Werte zurückgegeben.


Im zweiten Snippet stimmt das Muster einmal überein.

word 123-abc 23-rr 
\________________/ 

Es gibt zwei Erfassungen, daher werden zwei (2 * 1 = 2) -Werte zurückgegeben.

+0

Aber warum sind 2 Werte? wenn ich schreibe (...) *, nehmen asterisk maximale koinzidenzen, da es gierig ist, wenn ich recht darüber weiß – Log

+0

ich meine wieso mein bau nicht in erweitert/\ w + ([\ d \ w] +) \ - ([\ d \ w] +) ([\ d \ w] +) \ - ([\ d \ w] +) by engine – Log

+0

Wenn es das ist, was Sie wollen, dann sagen Sie ihm, es zu tun. Sonst wird es Leute davon abhalten, 'if (/(.)(?:(.)\2)*(.)/) {print $ 3}' – ikegami