2012-06-05 6 views
8

Następujące wyjścia "> Hut" w miejscu, w którym oczekuję wyjścia "Hut". Wiem to. * Jest chciwy, ale> musi być dopasowany i znajduje się poza grupą przechwytującą, więc dlaczego jest w moim podziale?C++ regex niezrozumienie

#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

Należy zauważyć, że prawdopodobnie obsługa implementacji regex jest nadal bardzo niska na gcc i MSVC. – inf

+0

dzięki, używam gcc 4.6.3. –

+0

Uaktualniłem do g ++ 4.7, ale wciąż ten sam wynik. Nadal uważam, że to nieporozumienie dotyczące wyrażeń regularnych z mojej strony. Zbyt często w przeszłości obwiniałem oprogramowanie o własne błędy. –

Odpowiedz

7

To jest błąd w implementacji libstdC++. Oglądać te:

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

Jeśli skompilować z gcc, pierwsza (libstdC++) zwraca całkowicie błędne Wynik 9, -2, 4 a drugi (wdrożenie Boost za) zwraca 5, 1, 3 zgodnie z oczekiwaniami.

Jeśli kompilujesz z clang + libC++, twój kod działa poprawnie.

(Zauważ, że libstdC++ 's regex realizacja jest tylko «częściowo obsługiwane», jak opisano w http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52719.)

+0

O, mój, to wyjątkowo denerwujące. Czy istnieje możliwość wyboru innej opcji składni? Nie, żebym * chciał * coś innego niż ECMA-Script ... ale jeśli to nie działa ... (Nawiasem mówiąc, teraz zacząłem się zastanawiać, dlaczego nie poszli z PCRE). –

+0

Nawiasem mówiąc, błąd nadal istnieje w GCC 4.7. –

+0

dziękuję za przykłady i wyjaśnienia. Sądzę, że nie jest w porządku oczekiwać wiele, jeśli jest to tylko częściowo obsługiwane. Będę albo używał boost albo unikam na razie wyrażeń regularnych. –

3

można zmodyfikować wyrażenie regularne tak, dopasowane części są podzielone na grupy:

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 
} 

wyjść :

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

Należy pamiętać, że grupy są określone przez bracets (/* your regex here */) i jeśli chcesz, aby część z bracet twoja ekspresja, następnie musisz uciec z niej \, która jest \\ w kodzie. Aby uzyskać więcej informacji, zobacz Grouping Constructs.

To pytanie może również pomóc: How do I loop through results from std::regex_search?

także nie używać using namespace std; na początku plików, to jest złą praktyką.

+0

Dziękuję za odpowiedź i za wskazówkę dotyczącą 'using namespace std;'. Doceniam wyjaśnienia! –