2015-12-16 5 views
4

В соответствии с https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#status.iso.2011 двигатель регулярного выражения стандарта C++ 11 должен быть заполнен в GCC. Теперь, может кто-нибудь объяснить мне, почему этот простой примерC++ 11 regexp и GCC

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


using namespace std; 


int main() 
{ 
    string string_array[] = {"http://www.cplusplus.com/reference/regex/regex_match/", 
          "tcp://192.168.2.1:1234/hello/how/are/you", 
          "https://mail.google.com/mail/u/0/?tab=wm#inbox/15178022db56df29?projector=1"}; 
    regex e("^(?:([A-Za-z]+):)?(\\/{0,3})([0-9.\\-A-Za-z]+)(?::(\\d+))?(?:\\/([^?#]*))?(?:\\?([^#]*))?(?:#(.*))?$"); 

    for(int i=0; i<3; i++) 
    { 
     smatch sm; 
     regex_match (string_array[i],sm,e); 

     for (unsigned i=0; i<sm.size(); ++i) 
     { 
      cout << "[" << sm[i] << "] "; 
     } 

     cout << endl; 
    } 
    return 0; 
} 

результаты в этой продукции (примечание, например, неправильно обрабатывались номер порта второй линии, но там, кажется, много ошибок)

[http://www.cplusplus.com/reference/regex/regex_match/] [http] [//] [www.cplusplus.com/reference/regex] [] [regex_match/] [] [] 
[tcp://192.168.2.1:1234/hello/how/are/you] [tcp] [//] [192.168.2.1:1234/hello/how/are/you] [] [] [] [] 
[https://mail.google.com/mail/u/0/?tab=wm#inbox/15178022db56df29?projector=1] [https] [//] [mail.google.com/mail/u/0/?tab=wm] [] [] [] [inbox/15178022db56df29?projector=1] 

в то время как его партнер python

import re 

string_array = ["http://www.cplusplus.com/reference/regex/regex_match/", 
         "tcp://192.168.2.1:1234/hello/how/are/you", 
         "https://mail.google.com/mail/u/0/?tab=wm#inbox/15178022db56df29?projector=1"] 
e = re.compile("^(?:([A-Za-z]+):)?(\\/{0,3})([0-9.\\-A-Za-z]+)(?::(\\d+))?(?:\\/([^?#]*))?(?:\\?([^#]*))?(?:#(.*))?$"); 

for i in range(len(string_array)): 
    m = e.match(string_array[i]) 
    print(m.groups()) 

правильно распечатывает это?

('http', '//', 'www.cplusplus.com', None, 'reference/regex/regex_match/', None, None) 
('tcp', '//', '192.168.2.1', '1234', 'hello/how/are/you', None, None) 
('https', '//', 'mail.google.com', None, 'mail/u/0/', 'tab=wm', 'inbox/15178022db56df29?projector=1') 

Я использую GCC 5.3.0 на ArchLinux

редактировать:

Я изменил программу этого, проверяя флаг регулярного выражения syntax_option_type

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


using namespace std; 


int main() 
{ 
    string string_array[] = {"http://www.cplusplus.com/reference/regex/regex_match/", 
          "tcp://192.168.2.1:1234/hello/how/are/you", 
          "https://mail.google.com/mail/u/0/?tab=wm#inbox/15178022db56df29?projector=1"}; 
    regex e("^(?:([A-Za-z]+):)?(\\/{0,3})([0-9.\\-A-Za-z]+)(?::(\\d+))?(?:\\/([^?#]*))?(?:\\?([^#]*))?(?:#(.*))?$"); 

    for(int i=0; i<3; i++) 
    { 
     smatch sm; 
     cout << "match: " <<regex_match (string_array[i],sm,e) << endl; 

     for (unsigned i=0; i<sm.size(); ++i) 
     { 
      cout << "[" << sm[i].str() << "] "; 
     } 
    } 

    cout << endl; 

    switch(e.flags()) 
    { 
     case regex_constants::basic: 
      cout << "POSIX syntax was used" << endl; 
      break; 
     case regex_constants::awk: 
      cout << "POSIX awk syntax was used" << endl; 
      break; 
     case regex_constants::ECMAScript: 
      cout << "ECMA syntax was used" << endl; 
      break; 
     case regex_constants::egrep: 
      cout << "POSIX egrep syntax was used" << endl; 
      break; 
    } 

    return 0; 
} 

и удивительно я получаю в конце

match: 1 
[http://www.cplusplus.com/reference/regex/regex_match/] [http] [//] [www.cplusplus.com/reference/regex] [] [regex_match/] [] [] match: 1 
[tcp://192.168.2.1:1234/hello/how/are/you] [tcp] [//] [192.168.2.1:1234/hello/how/are/you] [] [] [] [] match: 1 
[https://mail.google.com/mail/u/0/?tab=wm#inbox/15178022db56df29?projector=1] [https] [//] [mail.google.com/mail/u/0/?tab=wm] [] [] [] [inbox/15178022db56df29?projector=1] 
ECMA syntax was used 

это действительно, кажется, ошибка компилятора ..

+0

https://gcc.gnu.org/bugs/ –

+1

'regex_match' требует полного совпадения строк,' re.match' требует только совпадения в начале строки. –

+0

@stribizhev Хорошо, но поскольку regex_match возвращает true, например re.match (который возвращает объект соответствия), в чем разница? – woggio

ответ

0

Есть две проблемы:

  • Match object groups() против match_results разница
  • символы внутри классов символов, не должны быть экранированы

match object groups() в Python возвращает все субматрицы (захваченные подстроки), начиная с группы 1:

Возвращает кортеж, содержащий все подгруппы совпадения, от 1 до нескольких групп в шаблоне.

В match_results начинает перечисления всех групп, начиная с 0-й группы (весь матч):

В случае успеха, это не empty и содержит ряд sub_match объектов: первый sub_match элемент соответствует полное совпадение, и, если выражение регулярного выражения содержит подвыражения, которые должны быть сопоставлены (т. е. группы с разделителями в скобках), их соответствующие совпадения сохраняются как последовательные sub_match элементов в объекте match_results.

\ в группе 3 не избежать дефис, он игнорируется создавая тем самым диапазон между . и A (= [.-A] в нормальном мире регулярных выражений).

Вы не можете использовать escape-символы внутри классов символов в POSIX regex, считается ошибкой.Поместите дефис в конец, чтобы избежать необходимости избегать его (например, [0-9.A-Za-z-]+).

Таким образом, в Python, используйте

e = re.compile("^(?:([A-Za-z]+):)?(\\/{0,3})([0-9.A-Za-z-]+)(?::(\\d+))?(?:\\/([^?#]*))?(?:\\?([^#]*))?(?:#(.*))?$"); 

И в C++:

regex e("^(?:([A-Za-z]+):)?(\\/{0,3})([0-9.A-Za-z-]+)(?::(\\d+))?(?:\\/([^?#]*))?(?:\\?([^#]*))?(?:#(.*))?$"); 
// ... 
for(int i=0; i<3; i++) 
{ 
    smatch sm; 
    regex_match (string_array[i],sm,e); 

    for (unsigned i=1; i<sm.size(); ++i) // Here, start with the second element 
    { 
     cout << "[" << sm[i] << "] "; 
    } 

    cout << endl; 
} 

Сравнить Python demo и C++ demo.

+0

Почему вы не можете использовать escape-символы внутри классов символов в регулярном выражении C++? В любом случае я знал о том, что match_result возвращает целое совпадение, отличное от match.groups(), которое возвращает только подматрицы. Это не было одним из различий, которые я указывал, проблема была последней написал – woggio

+0

В POSIX я исправил себя. Хотя я все еще ищу ссылку. Я думал, что синтаксис ECMA использовался по умолчанию. –

+0

Я также думал, что по умолчанию был синтаксис ECMA, по крайней мере, согласно http: //www.cplusplus.com/reference/regex /, хотя я понимаю, что это не официальный источник информации. – woggio

0

Регулярное выражение работает правильно.

Изменить

cout << "[" << sm[i] << "] "; 

с

cout << "[" << sm[i].str() << "] "; 

и вы увидите правильный результат.

+0

Нет, я не вижу правильного результата, проблема была указана stribizhev – woggio

+0

Я тестирую ваш пример на vs2013 и получаю неправильный результат, который вы получаете вначале. Затем я меняю строку и вижу правильную строку, которую вы оцениваете. Но если у вас есть решение, все в порядке! – alangab

+0

Честно говоря, 'sm [i] .str()' более корректен, чем 'sm [i]', но это просто не проблема, эта часть кода работает хорошо. –

Смежные вопросы