Aufteilen einer verschachtelten Zeichenfolge, die Anführungszeichen enthält

8

Ich arbeite an einem Projekt in Java, das verschachtelte Zeichenfolgen benötigt.

Für eine Eingabezeichenfolge, die im Klartext wie folgt aussieht:

  

Dies ist "eine Zeichenkette" und dies ist "eine" verschachtelte "Zeichenkette"

Das Ergebnis muss folgendes sein:

%Vor%

Hinweis , dass die Sequenzen \" beibehalten werden sollen.
Ich habe die folgende Methode:

%Vor%

und ich muss ein Array von Strings aus dem gegebenen Parameter s nach den angegebenen Regeln erstellen, ohne das Java Collection Framework oder seine Derivate zu verwenden.

Ich bin unsicher, wie ich dieses Problem lösen soll.
Kann ein Regex-Ausdruck erstellt werden, der dies löst?

UPDATE basierend auf Fragen von Kommentaren :

  • jedes unescaped " hat sein Closing unescaped " (sie sind ausgeglichen)
  • Jedes Escaping-Zeichen \ muss ebenfalls mit Escapezeichen versehen werden, wenn wir ein Literal erstellen wollen, das es darstellt (um Text zu erzeugen, der \ repräsentiert, müssen wir es als \ schreiben).
dinomario10 29.03.2016, 18:43
quelle

3 Antworten

7

Sie können die folgende Regex verwenden:

%Vor%

Weitere Informationen finden Sie in der Regex-Demo

Java-Demo :

%Vor%

Erläuterung :

  • "[^"\]*(?:\.[^"\]*)*" - ein doppeltes Anführungszeichen gefolgt von 0+ Zeichen außer a " und \ ( [^"\] ) gefolgt von 0+ Sequenzen einer beliebigen Escape-Sequenz ( \. ) gefolgt von 0+ Zeichen außer a " und \
  • | - oder ...
  • \S+ - 1 oder mehr Nicht-Leerzeichen Zeichen

HINWEIS

@Pshemos Vorschlag - "\"(?:\\.|[^\"])*\"|\S+" (oder "\"(?:\\.|[^\"\\])*\"|\S+" wäre korrekter) - ist derselbe Ausdruck, aber viel weniger effizient seit dem verwendet eine mit * quantifizierte Alternationsgruppe. Dieses Konstrukt beinhaltet viel mehr Rückverfolgung, da die Regex-Engine jede Position testen muss, und es gibt 2 Wahrscheinlichkeiten für jede Position. Meine Unroll-the-Loop basierte Version wird Textstücke gleichzeitig abgleichen und ist daher viel schneller und zuverlässiger.

AKTUALISIEREN

Da String[] type als Ausgabe benötigt wird, müssen Sie dies in zwei Schritten tun: Zählen Sie die Übereinstimmungen, erstellen Sie das Array und führen Sie den Matcher dann erneut aus:

%Vor%

Siehe eine weitere IDEONE-Demo

    
Wiktor Stribiżew 29.03.2016, 18:51
quelle
7

Ein anderer Regex-Ansatz, der funktioniert, verwendet einen negativen Lookbehind: "words" ( \w+ ) ODER " zitieren gefolgt von etwas bis zum nächsten Zitat, dem kein Backslash vorangestellt ist ", und setzen Sie Ihre Übereinstimmung auf" global "(nicht bei der ersten Übereinstimmung zurück)

%Vor%

sehen Sie es hier .

    
sweaver2112 29.03.2016 18:53
quelle
1

Eine alternative Methode, die keine Regex verwendet:

%Vor%

Ausgabe:

  

[Dies ist "eine Zeichenkette", und dies ist "eine" verschachtelte "Zeichenkette"]

    
Majora320 29.03.2016 19:09
quelle

Tags und Links