2017-11-28 1 views

Antwort

2

Sie können die Anzahl der Übereinstimmungen mithilfe des Flags /g im Listenkontext zählen und diesen Wert in einen skalaren Kontext konvertieren.

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

for my $string (qw(fredwilmawilliamjohn fredwilmawilliamfred)) { 
    my $count =() = $string =~ m/(fred)/g; 
    if ($count == 1) { 
     say $string; 
    } 
} 

Der relevanteste Teil ist die =() =, die das Spiel in Liste Kontext zwingt. Die my $count wird dann diese Liste der Übereinstimmungen in einen skalaren Kontext zwingen, der Ihnen die Anzahl der Elemente in der Liste angibt. Das ist Ihre Anzahl an Übereinstimmungen.

+0

kann es mit rein regexp getan werden? $ _ = "Fredwilliamwilma"; if (/ regexp /) {print "Es gibt nur einen Fred in der Zeichenkette"} – SKS

+0

@SKS Sie meinen, Sie wollen die gesamte Logik in das Muster einfügen? Fred und Negativ schauen voraus, dass nichts oder nichts von Fred gefolgt ist, denke ich. Habe jetzt keinen Computer. Du musst es selbst versuchen. – simbabque

+1

'=() =' wird auch als 'Ziegenoperator' bezeichnet :) – Sobrique

0

Es klingt, als ob Sie das Muster abgleichen und sicherstellen möchten, dass es nicht in der Folge auftritt. Wie wäre es damit, mit negativen Look-Ahead-

m/fred(?!.*fred)/ 

Brechen it down:

?! - nicht von

gefolgt. * - null oder mehr Zeichen

+0

Dies wird nicht funktionieren, weil die Regexp versuchen wird, das negative Lookahead erfolgreich zu machen. Wenn es in der Zeichenfolge etwas findet, das nicht mit der zweiten Fred übereinstimmt, ist die Regex erfolgreich. '! m/fred (? =. * fred) /' würde hier funktionieren. –

+0

@ChrisCharley im Prinzip richtig, aber Sie sagen es nicht richtig.Diese Regex wird verhindern, dass sie mit der ersten Fred übereinstimmt, aber der Anfang der Regex wird in der Folge weiter versucht und mit der zweiten Fred verglichen (die keine Fred hat) – ysth

+0

@ysth Vielen Dank für die Klärung meiner Error. Ich sehe jetzt genau, wie die Regexp funktioniert. –

1
/fred(*COMMIT)(?!.*?fred)/s 

(*COMMIT) (in Perl 5.10 hinzugefügt) sagt nach fred passenden, nicht Rückzieher nicht und versuchen Sie es erneut, wenn der Rest der Anpassung Regex schlägt fehl. Der Rest der Regex sagt nicht übereinstimmen, wenn .*?fred (eine beliebige Anzahl von Zeichen gefolgt von Fred) an diesem Punkt, nach dem ersten fred übereinstimmt, d. H. Es gibt keine weitere fred.

Vor 5.10, müssen Sie den ersten fred in der Regex zwingen, mich nur auf den ersten fred wie so in der Zeichenfolge entsprechen:

/^(?:(?!fred).)*+fred(?!.*?fred)/s 

(so lange ein beliebige Anzahl von Zeichen übereinstimmen, wie sie sind nicht der Anfang von fred, bevor der fred gefunden wird, der dann nicht von einem anderen fred gefolgt werden kann.

Oder

/^(?>.*?fred)(?!.*?fred)/s 

(am Anfang der Zeichenfolge beginnen und ohne Rückzieher zu ermöglichen, finden die ersten fred, und behaupten, dass es keinen fred, nachdem es ist)

(Durchweg/s wird verwendet, um . mit einem beliebigen Zeichen zu vergleichen, nicht nur mit einem Nicht-Zeilenumbruchzeichen.)

Verwandte Themen