2012-12-07 7 views
7

UPDATE: Grazie per tutte le grandi risposte! Ho provato diversi schemi di espressioni regolari ma non ho capito perché m.matches() non stava facendo quello che penso dovrebbe fare. Quando sono passato a m.find() invece, oltre a regolare il modello regex, sono riuscito a ottenere da qualche parte.Pattern/Matcher group() per ottenere la sottostringa in Java?


mi piacerebbe abbinare un modello in una stringa Java e quindi estrarre la parte corrispondente utilizzando un'espressione regolare (come operatore di Perl $ &).

Questa è la mia stringa di origine "s": DTSTART;TZID=America/Mexico_City:20121125T153000 Voglio estrarre la parte "America/Mexico_City".

Pensavo di poter utilizzare Pattern and Matcher e quindi estrarre utilizzando m.group() ma non funziona come mi aspettavo. Ho provato a monkeying con diverse stringhe regex e l'unica cosa che sembra colpire su m.matches() è ".*TZID.*" che è inutile in quanto restituisce solo l'intera stringa. Qualcuno potrebbe illuminarmi?

Pattern p = Pattern.compile ("TZID*:"); // <- change to "TZID=([^:]*):" 
Matcher m = p.matcher (s); 
if (m.matches()) // <- change to m.find() 
    Log.d (TAG, "looking at " + m.group()); // <- change to m.group(1) 
+0

sembra una linea da un file ICS (iCal) - perché non usare http://ical4j.sourceforge.net/ o equivalente? – jrtc27

+0

Infatti. Ho iniziato con ical4j ma è stato scagliato da un errore durante l'analisi del file ics, quindi l'ho rimosso. Potrei provare di nuovo se ho bisogno di più funzionalità rispetto all'estrazione delle linee DTSTART. – wufoo

risposta

7

Si utilizza m.match() che cerca di corrispondere l'intera stringa, se si utilizzerà m.find(), cercherà per la partita interna, anche ho migliorato un po 'la tua espressione regolare di escludere il prefisso TZID con larghezza zero guardare dietro:

 Pattern p = Pattern.compile("(?<=TZID=)[^:]+"); // 
    Matcher m = p.matcher ("DTSTART;TZID=America/Mexico_City:20121125T153000"); 
    if (m.find()) { 
     System.out.println(m.group()); 
    } 
2

Manca un punto prima dell'asterisco. La tua espressione corrisponderà a qualsiasi numero di maiuscole D s.

Pattern p = Pattern.compile ("TZID[^:]*:"); 

si dovrebbe anche aggiungere un gruppo cattura a meno che non si desidera catturare tutto, compreso il "TZID" e la ":"

Pattern p = Pattern.compile ("TZID=([^:]*):"); 

Infine, si dovrebbe utilizzare l'API diritto di cercare la stringa, piuttosto di tentare di abbinare la stringa nella sua interezza.

Pattern p = Pattern.compile("TZID=([^:]*):"); 
Matcher m = p.matcher("DTSTART;TZID=America/Mexico_City:20121125T153000"); 
if (m.find()) { 
    System.out.println(m.group(1)); 
} 

Questo prints

America/Mexico_City 
2

Si utilizza il modello sbagliato, provate questo:

Pattern p = Pattern.compile(".*?TZID=([^:]+):.*"); 
Matcher m = p.matcher (s); 
if (m.matches()) 
    Log.d (TAG, "looking at " + m.group(1)); 

.*? corrisponderà nulla in principio fino a TZID=, poi TZID= corrisponderà ed un il gruppo inizierà e abbinerà tutto a :, il gruppo verrà chiuso qui e quindi : corrisponderà e .* corrisponderà al resto della stringa, ora è possibile ottenere quello che ti serve in group(1)

+0

Ho cancellato la mia risposta quasi identica a favore della tua. Hai avuto una regex leggermente migliore. – mikeslattery

6

Questo dovrebbe funzionare bene:

Pattern p = Pattern.compile("TZID=(.*?):"); 
Matcher m = p.matcher(s); 
if (m.find()) { 
    String zone = m.group(1); // group count is 1-based 
    . . . 
} 

Un'espressione regolare alternativa è "TZID=([^:]*)". Non sono sicuro di quale sia più veloce.

1

Perché non usare semplicemente spaccato come:

String origStr = "DTSTART;TZID=America/Mexico_City:20121125T153000"; 
    String str = origStr.split(":")[0].split("=")[1]; 
+0

Soluzione molto elegante. Grazie – wufoo