2016-09-24 4 views
0

Ich mag würde eine Regex erstellen, so dass ich eine Zeichenfolge in Java mit folgenden Einschränkungen aufteilen:Java Regex: Splitting basierend auf mehreren Bedingungen mit Ausnahmen

Any non-word character, except for: 
(a) Characters surrounded by ' ' 
(b) Any instance of := >= <= <> .. 

Damit für das folgende Beispiel string:

print('*'); x := x - 100 

ich kann das folgende Ergebnis in einem String[] erhalten:

print 
(
'*' 
) 
; 

x 

:= 

x 

- 

100 

Dies ist die regex Ich habe derzeit so weit:

str.split("\\s+|"+ 
      "(?=[^\\w'][^']*('[^']*'[^']*)*$)|" + 
      "(?<=[^\\w'])(?=[^']*('[^']*'[^']*)*$)|" + 
      "(?=('[^']*'[^']*)*$)|" + 
      "(?<=')(?=[^']*('[^']*'[^']*)*$)"); 

Aber das gibt mir folgendes Ergebnis:

print 
(
'*' 
) 
; 

x 

:  
= <!-- This is the problem. Should be above next to the : 

x 

- 

100 

UPDATE

ich jetzt habe gelernt, dass es nicht möglich ist, zu erreichen, dies mit Regex.

Ich kann jedoch immer noch keine externen oder Frameworks oder Lexer verwenden und muss Java-Methoden wie StringTokenizer verwenden.

+2

Sie können nicht tun (a) mit einem regulären Ausdruck, period. Eine Sprache mit übereinstimmenden Trennzeichenpaaren ist keine reguläre Sprache. Sie müssen einen richtigen Lexer schreiben/verwenden. – OrangeDog

+0

kann er nicht Lookback und Lookforward in irgendeiner Weise verwenden? – Gus

+0

@OrangeDog Aber es funktioniert gut mit der aktuellen Regex, jedoch nur mit einer der beiden Einschränkungen. Ist es nicht möglich, eine zusätzliche Regex für Constraint '(2)' hinzuzufügen? –

Antwort

1

Haftungsausschluss: Regex ist kein generischer Parser. Wenn der Text, den Sie lesen, eine komplexe Sprache mit verschachtelten Konstrukten ist, dann müssen Sie einen tatsächlichen Lexer und keine Regex verwenden. Z.B. Der folgende Code unterstützt "Zeichen umgeben von", was eine einfache Definition ist, aber wenn die Zeichen ' Zeichen enthalten können, benötigen Sie einen Lexer.

Verwenden Sie nicht split().

Ihr Code wird viel einfacher zu lesen und zu verstehen sein, wenn Sie eine find() Schleife verwenden. Es wird auch besser funktionieren.

Sie schreiben Ihre Regex, um anzugeben, was Sie in einer Iteration der find()-Schleife erfassen möchten. Sie können sich auf | verlassen, um das erste übereinstimmende Muster auszuwählen, also legen Sie zuerst spezifischere Muster an.

Pattern p = Pattern.compile("\\s+" + // sequence of whitespace 
          "|\\w+" + // sequence of word characters 
          "|'[^']*'" + // Characters surrounded by ' ' 
          "|[:><]=" + // := >= <= 
          "|<>" +  // <> 
          "|\\.\\." + // .. 
          "|.");  // Any single other character 
String input = "print('*'); x := x - 100"; 
for (Matcher m = p.matcher(input); m.find();) 
    System.out.println(m.group()); 

Ausgabe

print 
(
'*' 
) 
; 

x 

:= 

x 

- 

100 
Verwandte Themen