2012-06-05 16 views
8

Le seguenti uscite "> Hut" dove mi aspetto che emetta "Hut". Lo so. * È goloso ma> deve essere abbinato ed è al di fuori del gruppo di cattura quindi perché è nella mia submatch?C++ regex not understanding

#include <string> 
#include <regex> 
#include <iostream> 

using namespace std; 

int main() { 
     regex my_r(".*>(.*)"); 
     string temp(R"~(cols="64">Hut)~"); 
     smatch m; 
     if (regex_match(temp, m, my_r)) { 
       cout << m[1] << endl; 
     } 
} 
+0

nota che il supporto per l'implementazione di espressioni regolari è ancora molto basso su gcc e MSVC probabilmente anche. – inf

+0

grazie, sto usando gcc 4.6.3. –

+0

Ho aggiornato a g ++ 4.7, ma ho ancora lo stesso output. Continuo a pensare che questo sia un fraintendimento delle regex da parte mia. Troppo spesso ho incolpato il software per i miei errori in passato. –

risposta

7

Questo è un bug nell'implementazione di libstdC++. Guarda questi:

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

int main() { 
    { 
     using namespace std; 
     regex my_r("(.*)(6)(.*)"); 
     smatch m; 
     if (regex_match(std::string{"123456789"}, m, my_r)) { 
      std::cout << m.length(1) << ", " 
         << m.length(2) << ", " 
         << m.length(3) << std::endl; 
     } 
    } 

    { 
     using namespace boost; 
     regex my_r("(.*)(6)(.*)"); 
     smatch m; 
     if (regex_match(std::string{"123456789"}, m, my_r)) { 
      std::cout << m.length(1) << ", " 
         << m.length(2) << ", " 
         << m.length(3) << std::endl; 

     } 
    } 

    return 0; 
} 

Se si compila con gcc, il primo (libstdC++) restituisce il risultato del tutto sbagliato 9, -2, 4 e la seconda (implementazione del boost) restituisce 5, 1, 3 come previsto.

Se si compila con clang + libC++, il codice funziona correttamente.

(Si noti che libstdC++ s 'regex attuazione è solo "parzialmente supportato", come descritto in http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52719.)

+0

Oh mio, è singolarmente fastidioso. Qualche possibilità di scegliere un'altra opzione di sintassi? Non che io * volessi * qualcosa di diverso da ECMA-Script ... ma se ciò non funziona ... (tra l'altro, ho iniziato a chiedermi perché non sono andati con PCRE). –

+0

A proposito, il bug esiste ancora in GCC 4.7. –

+0

grazie per gli esempi e le spiegazioni. Immagino che non sia giusto da parte mia aspettarmi molto se è solo parzialmente supportato. Utilizzerò boost o eviterò espressioni regolari per il momento. –

3

È possibile modificare l'espressione regolare in modo che le parti corrispondenti sono suddivisi in gruppi:

std::regex my_r("(.*)>(.*)\\).*"); // group1>group2).* 
std::string temp("~(cols=\"64\">Hut)~"); 
std::sregex_iterator reg_it(temp.begin(), temp.end(), my_r); 

if (reg_it->size() > 1) { 
    std::cout 
     << "1: " << reg_it->str(1) << std::endl // group1 match 
     << "2: " << reg_it->str(2) << std::endl; // group2 match 
} 

uscite :

1: ~(cols="64" 
2: Hut 

Nota che i gruppi sono specificati da bracets (/* your regex here */) e se si vuole fare una parte di bracet la tua espressione, quindi devi scappare con \, che è \\ nel codice. Per ulteriori informazioni, vedere Grouping Constructs.

Questa domanda può anche aiutare: How do I loop through results from std::regex_search?

Inoltre non utilizzare using namespace std; all'inizio del file, si tratta di una cattiva pratica.

+0

Grazie per la risposta e per il suggerimento relativo all'utilizzo di namespace std; '. Apprezzo le spiegazioni! –