2016-06-01 10 views
-1

Ich bin für eine Regex, die nur übereinstimmt, wenn bestimmte Teilzeichenfolgen nicht vorhanden sind. Insbesondere - wenn eine Codezeile den Rückgabewert einer Methode nicht zuweist oder zurückgibt.Regex um Abwesenheit von Teilstring

Beispiele:

this.execute(); // should match 

var x = this.execute(); // no match 

return this.execute(); // no match 

Ich habe versucht, das verwenden folgende regex

^(?!.*=|return).*execute\(\).* 

Dies funktioniert mit Regex Tester usw. - aber ich bin "ungültig Perl Operator" Ausnahme erhalten, wenn in der Praxis unter Verwendung von .

Dank ..

+1

1) '^ (?!. * = | Return). * Execute \ (\). *' Funktioniert in Perl 5.8+ einwandfrei. 2) "ungültiger Perl-Operator" ist kein von Perl ausgegebener Fehler (und wenn es so ist, klingt es nicht wie ein Fehler, den die Regex-Engine auslösen würde). Bitte geben Sie den tatsächlichen Code an, den Sie ausgeführt haben. – ikegami

+1

Tipp: Das abschließende '. *' Ist nutzlos. – ikegami

+0

Siehe ['Was soll ich tun, wenn jemand meine Frage beantwortet?]] (Http://stackoverflow.com/help/someone-answers) – zdim

Antwort

0

Ich meine, die einfache Antwort ist, benutzen Sie einfach den ! Operator auf Ihrem Test, aber hier ist die Umwandlung in falls Sie sich wundern:
/expression/ =>/^(?!.*expression)/ (entweder verwenden DOTALL oder [^] in JavaScript)
/^expression/ =>/^(?!expression)/

1

nicht so sicher, ob ich die Frage verstehen, aber Sie könnten betrachten diesen einen Versuch. ^this.execute\(\);

1

Bei Situationen wie diesen ist es am besten, den "kleinsten gemeinsamen Nenner" in den Übereinstimmungen zu finden, die Sie von ähnlich aussehenden Strings unterscheiden möchten. In diesem Fall kann die var x ignoriert werden - Ihre Anforderungen werden erfüllt, indem Sie sagen "alles bevor der Methodenaufruf in Ordnung ist - der Methodenaufruf allein nicht." Diese Aussage ist wahrscheinlich ein bisschen zu eng, also lassen Sie es in "Anthing anders als Whitespace ändern, bevor der Methodenaufruf in Ordnung ist, andernfalls den Aufruf markieren". Was bedeutet;

my $method_call = qr/ (this \. \w+) \(/x; 
while (<$fh>) { 
    if (/^\s* $method_call /x) { 
     warn "Found method call on line $.: $1\n" 
    } 
} 

I $fh bin presumming ist ein Dateihandle an die Souce-Code-Datei. Ich habe auch einige Vermutungen gemacht, die Sie möglicherweise darüber tweenek, wie Sie einen Methodenaufruf definieren möchten - dh. Öffnungsklammer für Parameter ist obligatorisch. Die Verwendung von erweiterten Modus-Regexs ermöglicht die Verwendung von Leerzeichen in der Regex zum leichteren Lesen. Wenn Sie die Anführungsregel verwenden, können Sie auch auf eine Regex nach Namen innerhalb einer anderen verweisen, um die Dinge klarer zu machen.

Wenn auf der anderen Seite, können Sie auf das Vorhandensein von var x oder return vor dem ok geben, darauf zu bestehen wollen, können wir die Suche rückwärts - also explizit suchen die „ok“ Situationen und Flagge alle anderen Anrufe:

my $method_call = qr/ (this \. \w+) \(/x; 
while (<$fh>) { 
    next if/^ \s* return \s+ $method_call /x;   # return OK 
    next if/^ \s* var \s+ \w+ = \s+ $method_call /x; # var OK 

    warn "Found method call on line $.: $1\n" if /$method_call/ ; 
} 

Diese beiden sind ein wenig wortreich, zeigen aber deutlicher, was Sie zu tun versuchen.

1

Ich glaube nicht, dass wir hier genug Informationen haben. Ich sage dies, weil die folgenden Werke für mich in der Schale

~$ echo "execute()"| perl -ne 'print if /^(?!.*=|return).*execute\(\).*/' 
execute() 
~$ echo "return execute()"| perl -ne 'print if /^(?!.*=|return).*execute\(\).*/' 

~$ 

In dem obigen Code, ich bin ein Einzeiler in einer Schale, die Rohre eine Zeichenfolge in ein Perl-Programm ausgeführt wird. Das Perl-Programm druckt die Zeichenfolge, wenn sie mit der Regex übereinstimmt. Ich bekomme keine Fehler von Ihrer Regex.

Es ist möglich, dass der Fehler auf Ihre Perl-Version zurückzuführen ist oder dass etwas völlig anderes passiert.

Ich benutze Perl v5.22.2

+0

Wird die Eingabeaufforderung wirklich auf Ihren Ausgabezeilen angezeigt? Wie verwirrend! – ikegami

+0

Lawl, nein, tut es nicht. Ich war nicht sicher, wie man zeigt, dass es keine Ausgabe auf dem zweiten Befehl gibt, also fügte ich die ~ $ –

+0

hinzu Fügen Sie ein abschließendes '~ $', oder 'print // hinzu? "match \ n": "keine Übereinstimmung \ n" 'oder' print //? "$ _ passt \ n": "$ _ passt nicht \ n" ' – ikegami

2

Da Sie nur Zuordnung ausschließen oder senden Sie es leicht

negiert ist
while (<DATA>) { print if not /(?:=|return)\s+this\.execute/ } 

__DATA__ 
this.execute(); 
var x = this.execute(); 
return this.execute(); 

Diese druckt nur die Linie this.execute();.


Mit Lookaround Assertions, ein negative Vorschau, die Sie anbieten funktioniert

if (/^(?!.*=|return)\s+this\.execute/x) { print "$_\n" } 

Was die negativen Lookbehind, gibt es ein Problem. Erstens ist hier, was

if (/(?<! =\s)  this\.execute/x) { print "$_\n" } 
if (/(?<! return \s) this\.execute/x) { print "$_\n" } 

arbeitet Dies schließt =oderreturn, mit einem Raum. Die Sache ist, wir können \s+ dort nicht setzen, noch können wir Alternation machen - Perl kann es für diese bestimmte Behauptung nicht tun, sieh perlretut. Wir bekommen

 
Variable length lookbehind not implemented in regex m/(?<!=\s+)this\.execute/ at 

wir hinzufügen können, Raum \s+ außerhalb der Behauptung, mit Gegen this... und dann mehrere Bedingungen kombinieren für eine Möglichkeit zu schaffen, dass es keinen Raum zwischen = und this... ist.

Es gibt jedoch keinen Grund dafür, wenn Sie eine reguläre negierte Übereinstimmung verwenden können.


Der gemeldete Fehler kann nur über grundlegende Syntax sein. Es geht um den genauen Code, den Sie ausführen, nicht um die Regex.

Verwandte Themen