2011-08-27 13 views
11

Ecco modello semplice: [key]: [value1] [value2] [value3] [valueN]Java 6 regex più corrispondenze di un gruppo

voglio ottenere:

  1. chiave
  2. matrice di valori

Ecco il mio regex: ^([^:]+):(:? ([^ ]+))++$

Ecco il mio testo: foo: a b c d

Matcher mi dà 2 gruppi: foo (come chiave) e d (come valori).

Se utilizzo +? anziché ++ ottengo a, non d.

Quindi java mi restituisce la prima (o l'ultima) occorrenza del gruppo.

Non riesco a utilizzare find() qui perché c'è solo una corrispondenza.

Cosa posso fare tranne la divisione della regex in 2 parti e utilizzando find per l'array di valori? Ho lavorato con espressioni regolari in molti altri ambienti e quasi tutti hanno la possibilità di recuperare "prima occorrenza del gruppo 1", "seconda occorrenza del gruppo 1" e così via.

Come posso fare con java.util.regex in JDK6?

Grazie.

+0

Potete per favore chiarire il punto circa che vi sia "solo * uno * partita?" Non c'è modo di catturare un numero indeterminato di partite come te lo chiedi, quindi qui è necessaria qualche iterazione. – seh

+0

È già il 2013 e non esiste ancora una soluzione decente a questo problema! * facepalm * – altern

risposta

9

Il numero totale di gruppi di corrispondenze non dipende dalla stringa di destinazione ("foo: a b c d", nel tuo caso), ma dal modello. Il tuo modello avrà sempre 3 gruppi:

^([^:]+):(:? ([^ ]+))++$ 
^  ^^
|  | | 
1  2 3 

Il 1 ° gruppo terrà la chiave, e il gruppo 2 °, che corrisponde lo stesso di gruppo 3, ma poi comprende uno spazio bianco, sarà sempre tieni solo 1 dei tuoi valori. Questo è o il primo valore (in caso di ungreedy +?) o l'ultimo valore (in caso di abbinamento avido).

cosa si potrebbe fare è solo corrisponde:

^([^:]+):\s*(.*)$ 

in modo da avere i seguenti incontri:

- group(1) = "foo" 
- group(2) = "a b c d" 

e poi dividere il gruppo 2 ° su di esso sta spazi bianchi per ottenere tutti valori:

import java.util.Arrays; 
import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

public class Main { 
    public static void main (String[] args) throws Exception { 
    Matcher m = Pattern.compile("^([^:]+):\\s*(.*)$").matcher("foo: a b c d"); 
    if(m.find()) { 
     String key = m.group(1); 
     String[] values = m.group(2).split("\\s+"); 
     System.out.printf("key=%s, values=%s", key, Arrays.toString(values)); 
    } 
    } 
} 

che stamperà:

key=foo, values=[a, b, c, d] 
+0

Uno, penso che intendesse '(?:' not '(:?'. Ma, cosa più importante, questo viene chiesto un bel po'.Credo che C# abbia un modo per farlo. Potrebbe essere utile estendere l'API in modo che si possa recuperare una serie di corrispondenze per il gruppo Nᵗʰ tramite 'group_array (N)' o qualcosa del genere: è necessario un nuovo flag di compilazione del pattern per abilitarlo, dal momento che è troppo costoso per uso generale. potrebbe usare matrici '@ 1' e' @ 2' invece di scalari '$ 1' e' $ 2', e anche definire '$ 1' per significare' $ 1 [$ # 1] 'ecc. È utile, malvagio, o entrambi? :) – tchrist

+0

@tchrist, sì, potresti avere ragione riguardo a ':?' <-> '?:'. Non ho familiarità con C#, e non ho mai sentito parlare di questa funzione di raggruppamento N (hai un collegamento a MSDN documenti per me?). E sarebbe sicuramente sia utile che malvagio! :) –

+0

cosa mi fa inquinare me stesso? :) [Questo lo suggerisce] (http://msdn.microsoft.com/en-us/library/30wbz966 (v = vs.71) .aspx # Y2320) in Acquisisci e sotto Acquisisci. Ho problemi a leggerlo, però. :) – tchrist

2
Scanner s = new Scanner(input).useDelimiter(Pattern.compile(":?\\s+")); 
String key = s.next(); 
ArrayList values = new ArrayList(); 
while (s.hasNext()) { 
    values.add(s.next()); 
} 
System.out.printf("key=%s, values=%s", key, values); 

Esso stampa:

key=foo, values=[a, b, c, d] 
Problemi correlati