2015-12-05 7 views
5

Szukam regex, który będzie podzielić ciąg w następujący sposób:Regex do podziału w każdej postaci, ale utrzymując numery wraz

String input = "x^(24-3x)"; 
String[] signs = input.split("regex here"); 
for (int i = 0; i < signs.length; i++) { System.out.println(sings[i]); } 

z wyjściem skutkuje:

"x", "^", "(", "24", "-", "3", "x", ")" 

ciąg jest podzielony na każdą postać. Jeśli jednak obok siebie znajdują się cyfry, powinny one pozostać zgrupowane w jednym ciągu.

Odpowiedz

4

Można użyć tej lookaround regex oparta:

String[] signs = input.split("(?<!^)(?=\\D)|(?<=\\D)"); 

RegEx Demo

REGEX Breakup

(?<!^)(?=\\D) # assert if next char is non-digit and we're not at start 
|    # regex alternation 
(?<=\\D)  # assert if previous character is a non-digit 
+1

perfekcyjnie, nawet z wyjaśnieniem. Dziękuję Ci. – Zi1mann

+1

bardzo sprytny, bardzo podchwytliwy –

+0

Czy możesz podzielić się, dlaczego czek na nie bycie na początku jest potrzebny? Przetestowałem to z trzema testowymi przypadkami -> "," 123 "," aa123 "i we wszystkich trzech przypadkach uzyskałem taki sam wynik, niezależnie od tego, czy to uwzględniam, czy nie. Regex101 pokazuje różnicę dla PCRE, ale dla Javy nie widzę żadnej różnicy w wynikach. –

0

można również użyć wzoru i dopasowywania do podziału na tokeny, które jest raczej czytelny

String regex="\\d+|[a-z]+|[\\-()\\^]"; 
String str="x^(24-3x)"; 

jeśli działa równie łatwo przy str = "xxx^(24-3xyz)";

Aby uzyskać wszystkie żetony, to trochę skomplikowane:

Używam tego:

uprzejmości: Create array of regex matches

for (MatchResult match : allMatches(Pattern.compile(regex), str)) { 
    System.out.println(match.group() + " at " + match.start()); 
} 

public static Iterable<MatchResult> allMatches(
     final Pattern p, final CharSequence input) { 
    return new Iterable<MatchResult>() { 
    public Iterator<MatchResult> iterator() { 
     return new Iterator<MatchResult>() { 
     // Use a matcher internally. 
     final Matcher matcher = p.matcher(input); 
     // Keep a match around that supports any interleaving of hasNext/next calls. 
     MatchResult pending; 

     public boolean hasNext() { 
      // Lazily fill pending, and avoid calling find() multiple times if the 
      // clients call hasNext() repeatedly before sampling via next(). 
      if (pending == null && matcher.find()) { 
      pending = matcher.toMatchResult(); 
      } 
      return pending != null; 
     } 

     public MatchResult next() { 
      // Fill pending if necessary (as when clients call next() without 
      // checking hasNext()), throw if not possible. 
      if (!hasNext()) { throw new NoSuchElementException(); } 
      // Consume pending so next call to hasNext() does a find(). 
      MatchResult next = pending; 
      pending = null; 
      return next; 
     } 

     /** Required to satisfy the interface, but unsupported. */ 
     public void remove() { throw new UnsupportedOperationException(); } 
     }; 
    } 
    }; 
} 
Powiązane problemy