2016-07-05 12 views
0

Ich mache ein Programm in Java und habe ein kleines Problem mit Regular Expressions. Ich möchte alles erfassen, was nicht in Anführungszeichen steht. Ich habe ein Regex-Muster dafür, right here, aber das Problem ist, es kann nicht in Java verwendet werden. Es verwendet den (*SKIP)(*F) Trick, um über die ".*" zu überspringen, und finden Sie alles andere (mit [^\W]), aber wie gesagt, es kann nicht in Java verwendet werden. Ich habe ein anderes Muster, das nah ist, aber nicht ganz das, was ich brauche, right here. Es findet alles, was keine Anführungszeichen hat, direkt davor oder dahinter. Das Problem mit diesem, ist, dass, wenn ich etwas wie dieses habe: Test1 "Hello World!" Test2, und wird Test1, Test2, UND World greifen. Ich möchte nicht World bekommen, weil es in den Zitaten steht. Was ich wissen möchte, ist, wenn es überhaupt möglich ist, zu tun, was ich will und wie wenn.Gibt es eine einfache Java Regex (* SKIP) (* F) Alternative?

+0

Wenn Sie sich über Anführungszeichen sicher sind, tut diese einzelne Regex '[^"] ++ ((? = "(? <= \ B)) | \ s * $)" es. [Demo] (https://regex101.com/r/rX4aY1/1) – revo

+0

@revo Die Sache ist, es ergreift die Räume. Gibt es eine Möglichkeit, die Leerzeichen nicht zu bekommen, so wie '' '' '(^ Ich kann es nicht herausfinden: P) – mttprvst13

+0

Ich werde eine Antwort hinzufügen. – revo

Antwort

0

Diese Verben sind eine sehr nützliche Möglichkeit, der Regex-Engine (in diesem Fall PCRE) mitzuteilen, dass Sie diese Übereinstimmungen verwerfen möchten.

Java nicht über diese Verben, aber Sie können, ohne dass die Verben den gleichen Ansatz auf Java verwenden (*SKIP)(*F), und dann fangen die Inhalte, die Sie wollen ... so können Sie verwenden:

".*"|([^\W]+) 
or 
".*"|(\w+) 

Und dann greifen der Inhalt von der Erfassungsgruppe 1.

String text = "test1 \"hello world!\" test2"; 

Pattern ptrn = Pattern.compile("\".*\"|([^\\W]+)"); 
Matcher m = ptrn.matcher(text); 

while (m.find()) { 
    if (m.group(1) != null) { 
     System.out.println("Text: "+m.group(1)); 
    } 
} 

IDEOne Demo

Dies ist als Verwerfungs Technik gut bekannt, wo Sie alle Muster verwerfen können, die nicht erfasst werden, und konzentrieren sich auf die, die Sie zum Beispiel erfassen möchten, wenn Sie:

".*"|'.*'|`.*`|([^\W]+) 

Dies umso übereinstimmen Muster aber Conly erfassen die letzte

Regular expression visualization

+0

Nun, die Art, wie ich es mache, ist etwa so: https://ideone.com/4BdyeB und basierend auf der Ausgabe funktioniert es nicht. Gibt es eine Problemumgehung? – mttprvst13

+0

@ mttprvst13 Sie müssen den Inhalt von Capturing-Gruppe mit 'm.group (1)' greifen, das ist der Trick. In meiner Antwort können Sie die IDEOne Demo finden, um zu sehen, wie es funktioniert –

1

Sie müssen übereinstimmen, die Inhalte, die Sie wollen, zu vermeiden und eine Capture-Gruppe zu verwenden, um herauszufiltern, was Sie wollen (ich glaube nicht, dass es eine andere Art und Weise ist) . Ein praktisches Muster dafür kann sein:

(?:[^\w"]+|"[^"]*")*+(\w+) 

, die ein Ergebnis in der Erfassungsgruppe 1 für jede Übereinstimmung zurückgibt. demo

Hinweis: Wenn Sie das Muster für einen Ersatz verwenden möchten, setzen Sie den ersten Teil in einer Capture-Gruppe zu und die Ersatzzeichenfolge mit einem Verweis auf diese Gruppe starten:

((?:[^\w"]+|"[^"]*")*+)(\w+) 

Andere Art und Weise, Split Ihre Zeichenfolge mit: (?:[^\w"]+|"[^"]*")+

Sie können "[^"]*" zu "[^"\\]*+(?s:\\.[^"\\]*)*+"? ändern, um migrierte Anführungszeichen in Anführungszeichen und ein eventuell fehlendes Anführungszeichen zu behandeln.

1

Leider kann ich andere Beiträge noch nicht kommentieren, aber Federico Piazza Lösung wird fehlschlagen, wenn es mehrere Sätze von Anführungszeichen gibt.Zum Beispiel, wenn Ihr Text war die folgende:

String text = "test1 \"hello world!\" test2 \"foobar\" test3"; 

In diesem Fall wäre es

test1 
test3 

drucken und vollständig test2

Statt das Muster

Pattern ptrn = Pattern.compile("\".*?\"|([\\w]+)"); 

Die ? verwenden überspringen wird den Operator .* nicht gierig und finden das nächste Zitat und nicht das letzte Zitat. Um also seine Antwort im Wesentlichen zu kopieren, könnten Sie Folgendes tun.

String text = "test1 \"hello world!\" test2 \"foobar\" test3"; 

Pattern ptrn = Pattern.compile("\".*?\"|([\\w]+)"); 
Matcher m = ptrn.matcher(text); 

while (m.find()) { 
    if (m.group(1) != null) { 
     System.out.println("Text: "+m.group(1)); 
    } 
} 
+0

Guter Fang auf der gierigen vs nicht gierigen Bearbeitung. Das war ein unglücklicher Tippfehler, der meine Bedeutung völlig veränderte. – gottfred

0

Sie wollen also außerhalb von Anführungszeichen mit ohne Leerzeichen:

[^"\s]++((?=\s*"[^\s])|(?=\s*$)|(?=[^"]+\s+")) 

Live demo

Es schlägt fehl, wenn:

  1. Es gibt keine Leerzeichen vor einer Öffnung Zitat ist.
  2. Es gibt ein Leerzeichen vor einem Schlusskurs.
  3. In Ihrer Eingabe sind verschachtelte oder unerwünschte Anführungszeichen enthalten.

So funktioniert es regelmäßig nur auf OPs solche regelmäßigen Eingaben.

+0

Nur FYI, '(? <= \ B)' ist das gleiche wie '(? = \ B)' ist das gleiche wie '\ b'. –

+0

Sie haben einen guten Punkt gemacht, aber es wird überhaupt nicht benötigt. Ich habe es entfernt. @AlanMoore – revo