2009-07-10 10 views
3

zu entsprechen Ich versuche, Teile von JS-Code zu vergleichen und String-Literale, die ein bestimmtes Schlüsselwort enthalten, mit Java zu extrahieren.Regexp, um Javascript String-Literale mit einem bestimmten Schlüsselwort mit Java

Nach dem Versuch, mit meinem eigenen regexp zu kommen, dies zu tun, beenden ich diesen generali String-wörtliche Übereinstimmung mit regulärem Ausdruck Modifizieren bis (Pattern.COMMENTS verwendet, wenn die Muster in Java Aufbau):

 
(["']) 
(?:\\?+.)*? 
\1 

auf dem

folgenden
 
(["']) 
(?:\\?+.)*? 
keyword 
(?:\\?+.)*? 
\1 

Die Testfälle:

var v1 = "test"; 
var v2 = "testkeyword"; 
var v3 = "test"; var v4 = "testkeyword"; 

Die regexp korrekt d oesn't Match Linie 1 und Linie passt richtig 2.

jedoch in Zeile 3, statt nur "testkeyword" passend, passt es die Chunk

"test"; var v4 = "testkeyword" 

was falsch ist - die regexp entsprach dem ersten double quote und endete nicht beim zweiten doppelten Zitat und ging bis zum Ende der Zeile.

Hat jemand irgendwelche Ideen, wie man das beheben kann?

PS: Bitte beachten Sie, dass die Regexp innerhalb von String-Literalen (die der generalisierte Matcher bereits getan hat) korrekt geflüchtete Einzel- und doppelte Anführungszeichen behandeln muss.

Antwort

3

Wie über diese Änderung:

(?: 
    " 
    (?:\\"|[^"\r\n])* 
    keyword 
    (?:\\"|[^"\r\n])* 
    " 
| 
    ' 
    (?:\\'|[^'\r\n])* 
    keyword 
    (?:\\'|[^'\r\n])* 
    ' 
) 
+0

Perfekt! Funktioniert wie benötigt! – niktech

1

Nach viel Revision (siehe Versionsgeschichte, die Zuschauer zu Hause :), ich glaube, das ist meine letzte Antwort lautet:

(?: 
    " 
    (?:\\?+"|[^"])* 
    keyword 
    (?:\\?+"|[^"])* 
    " 
| 
    ' 
    (?:\\?+'|[^'])* 
    keyword 
    (?:\\?+'|[^'])* 
    ' 
) 
+0

Es tut, wenn ich es teste ... Testfall 3 passt richtig als 2-String-Literale. Hier ist, wo der ursprüngliche Regex kam von http://blog.stevenlevithan.com/archives/match-quoted-string – niktech

+0

Hoppla, ich verstehe. Ja, es beruht auf dem nicht-gierigen Verhalten, das Sie nicht auf die gleiche Weise verwenden können, da Sie an einem Keyword verankern. Bearbeiten ... – chaos

+0

Das sollte funktionieren, aber das Problem wäre in meinem Fall falsch-positiv. Die Wahrscheinlichkeit für ein Zeichenfolgenliteral mit dem speziellen Schlüsselwort beträgt etwa 1%. Und ich muss jedes Mal viele Dateien mit Hunderten von Zeilen verarbeiten. Wenn niemand einen Weg finden kann, die Literale für das spezielle Schlüsselwort vor der Verarbeitung zu überprüfen, gehe ich mit Ihrer Lösung fort. – niktech

0

Sie müssen zwei schreiben Muster für einzelne oder doppelte Zeichenketten in Anführungszeichen, da es keine Möglichkeit gibt, die Regex daran zu erinnern, welche die Zeichenkette geöffnet hat. Dann kannst du oder sie zusammen mit |.

0

Verwenden Sie Code aus Rhino - JS in Java -, um die echten String-Literale zu erhalten.

Oder, wenn Sie Regex verwenden möchten, eine Suche für das gesamte Literal, dann einen verschachtelten Test, wenn das Literal 'Schlüsselwort' enthält.

Ich denke, dass Tims Konstruktion funktioniert, aber ich würde nicht darauf in allen Situationen wetten, und die Regex müsste wahnsinnig unhandlich werden, wenn sie sich mit Literalen befassen müsste, die nicht gefunden werden wollen durch deine Tests schleichen). Zum Beispiel:

var v5 = "test\x6b\u0065yword" 

unterscheiden sich von der Lösung, meine Geheimwaffe für die interaktive Regexes Ausarbeiten ist ein Werkzeug, das ich genannt Regex Powertoy gemacht, die im Gegensatz zu vielen dieser Utilities läuft in jedem Browser mit Java-Applet-Unterstützung.

 
string-literal ::= quote text quote 

text ::= character text 
     | character 

character ::= non-quote 
      | backslash quote 

mit nicht-Zitat, Backslash und Zitat zu sein Terminals:

+0

Der von Ihnen erwähnte Testfall trifft nicht auf meine Situation zu. Ich bin sicher, dass "Schlüsselwort" genau so erscheint, in ASCII. Zwei Tests (erster Test für String-Literal, dann Test für das Vorhandensein eines Schlüsselworts) führen in meinem Fall zu einer Menge von falsch-positiven Ergebnissen, da die Wahrscheinlichkeit, dass ein Literal ein Schlüsselwort hat, ungefähr 1% beträgt. – niktech

0

Eine Grammatik ein Stringliteral würde etwa so aussehen zu konstruieren.

Eine Grammatik ist regulär, wenn sie kontextfrei ist (dh die linke Seite aller Regeln ist immer ein einzelnes Nicht-Terminal) und die rechte Seite aller Regeln immer entweder leer ist, ein Terminal oder ein Terminal folgt durch ein Nicht-Terminal.

Möglicherweise stellen Sie fest, dass die erste oben angegebene Regel ein Terminal hat, gefolgt von einem Nonterminal gefolgt von einem Terminal. Dies ist also keine reguläre Grammatik.

Ein regulärer Ausdruck ist ein Ausdruck, der reguläre Sprachen analysieren kann (Sprachen, die mit einer normalen Grammatik erstellt werden können). Es ist nicht möglich, nicht reguläre Sprachen mit regulären Ausdrücken zu analysieren.

Die Schwierigkeit, eine geeignete reguläre Expression zu finden, rührt daher, dass ein passender regulärer Ausdruck nicht existiert. Sie werden niemals zu einem Code kommen, der offensichtlich korrekt ist.

Es ist viel einfacher, einen einfachen Parser nach den obigen Regeln zu schreiben. Da der Text enthält durch Ihre Zeichenfolge Literalen ist regulär, können Sie einen einfachen regulären Ausdruck verwenden, um nach Ihrem Stichwort zu suchen --- nach Sie extrahiert diesen Text aus seiner Umgebung.

+0

Interessante Beobachtung. Hast du zufällig einen Testfall, der Tims Lösung kaputt macht? Es scheint sich um alle meine Testfälle zu halten. – niktech