2012-06-05 10 views
8

Las siguientes salidas "> Hut" donde espero que salga "Hut". Sé que. * Es codicioso, pero> debe coincidir y está fuera del grupo de captura, entonces ¿por qué está en mi subcoincidencia?C++ regex no comprende

#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

tenga en cuenta que la compatibilidad con la implementación de expresiones regulares todavía es muy baja en gcc y MSVC, probablemente también. – inf

+0

gracias, estoy usando gcc 4.6.3. –

+0

Actualicé a g ++ 4.7, pero igual salida. Todavía creo que esto es un malentendido de expresiones regulares de mi parte. Con demasiada frecuencia he culpado al software por mis propios errores en el pasado. –

Respuesta

7

Esto es un error en la implementación de libstdC++. Mira estas:

#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; 
} 

Si se compila con gcc, el primero (libstdC++) devuelve el resultado totalmente equivocado 9, -2, 4 y el segundo (aplicación del impulso) devuelve 5, 1, 3 como se esperaba.

Si compila con clang + libC++, su código funciona bien.

(Tenga en cuenta que libstdC++ 's aplicación de expresiones regulares es solamente 'parcialmente apoyado', como se describe en http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52719.)

+0

Oh mi, eso es singularmente molesto. ¿Alguna posibilidad de elegir otra opción de sintaxis? No es que quiera * algo * que no sea ECMA-Script ... pero si eso no funciona ... (de paso, ahora me he preguntado por qué no fueron con PCRE). –

+0

Por cierto, la falla aún existe en GCC 4.7. –

+0

gracias por los ejemplos y explicaciones. Supongo que no es justo por mi parte esperar mucho si solo es parcialmente compatible. Usaré impulso o evitaré las expresiones regulares por el momento. –

3

Puede modificar su expresión regular para que las partes coincidentes se dividen en grupos:

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 
} 

salidas :

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

Tenga en cuenta que los grupos son especificados por bracets (/* your regex here */) y si desea hacer una parte de bracet su expresión, entonces necesita escapar con \, que es \\ en el código. Para obtener más información, vea Grouping Constructs.

Esta pregunta también le puede ayudar: How do I loop through results from std::regex_search?

Tampoco utilices using namespace std; al comienzo de sus archivos, que es una mala práctica.

+0

Gracias por su respuesta y por su sugerencia con respecto a 'using namespace std;'. Aprecio las explicaciones! –