2010-06-28 11 views
5

Sto cercando di analizzare una stringa di input utilizzando un'espressione regolare. Sto riscontrando un problema quando tento di catturare un gruppo ripetuto. Mi sembra sempre che ci sia l'ultima istanza del gruppo. Ho provato a usare quantificatori riluttanti (non avidi), ma mi sembra che manchi qualcosa. Qualcuno può aiutare?Come posso acquisire tutte le corrispondenze di un gruppo ripetuto con Boost :: regex_search?

espressione regolare cercato:

(OS)\\s((\\w{3})(([A-Za-z0-9]{2})|(\\w{3})(\\w{3}))\\/{0,1}){1,5}?\\r 

(OS)\\s((\\w{3}?)(([A-Za-z0-9]{2}?)|(\\w{3}?)(\\w{3}?))\\/{0,1}?){1,5}?\\r 

stringa di input:

OS BENKL/LHRBA/MANQFL\r\n 

mi sembra sempre di ottenere ultimo gruppo, che è il gruppo MANQFL (MAN QFL), e il mio scopo è quello di ottenere tutti e tre i gruppi (non ci può essere 1-5 gruppi):

(BEN KL) , (LHR BA) and (MAN QFL). 

C++ frammento di codice:

std::string::const_iterator start = str.begin(), end = str.end(); 
while(regex_search(start,end,what,expr)) 
{ 
    cout << what[0]; 
    cout << what[1]; 
    ... 
    start += what.position() + what.length(); 
} 

Questo ciclo si eccita solo una volta, mentre mi aspetto che venga eseguito 3 volte in questo esempio. Qualsiasi aiuto sarà molto apprezzato.

+0

Sarebbe di grande aiuto se tu ci dicessi di più sul formato dell'input e su come lo vuoi analizzare. –

+0

Input è il flusso di stringhe e in questo esempio mi aspetto di ottenere 3 gruppi (BEN KL), (LHR BA) e (MAN QFL). So che in questo caso possiamo farlo anche senza usare espressioni regolari, ma sto solo cercando di capire se posso mantenerlo coerente con il codice esistente in cui viene usata la regex. – omshanti

risposta

0

Questo è il comportamento previsto: quando un gruppo di acquisizione è controllato da un quantificatore, ogni ripetizione sovrascrive ciò che è stato catturato la volta precedente. Il modo più semplice per ottenere tutte le partite sarebbe quella di mettere un gruppo di cattura in tutto il tutto, in questo modo:

(OS)\\s(((\\w{3})(([A-Za-z0-9]{2})|(\\w{3})(\\w{3}))\\/?){1,5})\\r 

Quel gruppo finirà contenente BENKL/LHRBA/MANQFL, che è possibile dividere il /.

1

L'unico sapore regex che so che può darti tutte le iterazioni di un gruppo di cattura è il sapore regex .NET. Normalmente un motore regex salva solo l'ultima iterazione di ogni gruppo di cattura.

La soluzione generale a questo tipo di problema consiste nell'utilizzare una regex per acquisire tutte le iterazioni del gruppo e una seconda regex per dividere il risultato della prima espressione regolare negli elementi separati. Alan ha già spiegato come puoi farlo in questa particolare situazione.

4

Il modo migliore per ottenere più corrispondenze di boost :: regex consiste nell'utilizzare regex_iterators. Questo esempio dovrebbe fare ciò che vuoi.

#include <iostream> 
#include <string> 
#include <boost/regex.hpp> 

int main() { 
    std::string a = "OS BENKL/LHRBA/MANQFL\r\n"; 
    const boost::regex re("[A-Z]{3}[A-Z]*"); 
    boost::sregex_iterator res(a.begin(),a.end(),re); 
    boost::sregex_iterator end; 
    for (; res != end; ++res) 
     std::cout << (*res)[0] << std::endl; 
}