2014-10-17 4 views
0

У меня есть код, который проходит через файл, чтобы найти даты, но не возвращает его, что он нашел совпадение с моим регулярным выражением.Регулярное выражение, не найденное совпадение

КОД:

std::string s(line); 
std::smatch m; 
std::regex e("^[0,1]?\d{1}\/(([0-2]?\d{1})|([3][0,1]{1}))\/(([1]{1}[9]{1}[9]{1}\d{1})|([2-9]{1}\d{3}))$"); 
std::cout << "Target sequence: " << s << std::endl; 
std::cout << "Regular expression: ^[0,1]?\d{1}\/(([0-2]?\d{1})|([3][0,1]{1}))\/(([1]{1}[9]{1}[9]{1}\d{1})|([2-9]{1}\d{3}))$" << std::endl; 
std::cout << "The following matches and submatches were found:" << std::endl; 

while (std::regex_search(s, m, e)) { 
    for (auto x : m) std::cout << x << " "; 
    std::cout << std::endl; 
    s = m.suffix().str(); 
} 

ВЫВОД:

Success 
Target sequence: 12/28/2002  2 15 38 43 50 
Regular expression: ^[0,1]?d{1}/(([0-2]?d{1})|([3][0,1]{1}))/(([1]{1}[9]{1}[9]{1 
}d{1})|([2-9]{1}d{3}))$ 
The following matches and submatches were found: 
Enter q to quit: 

Это мое регулярное выражение не правильно или что-то еще?

+0

Это не исправляет материал, а просто упрощает ваше регулярное выражение: '^ [0,1]? \ D \/(([0-2]? \ D) | (3 [0,1])) \/((199 \ d) | ([2-9] \ d {3})) $ ' – nhahtdh

+0

@nhahtdh спасибо –

ответ

3

Причина в своем регулярном выражении и в том, как вы определяете строковый литерал:

  • Перед тем, как делать какие-либо исправления в своем регулярном выражении, попытайтесь распечатать строку литерал консоли:

    std::cout << "^[0,1]?\d{1}\/(([0-2]?\d{1})|([3][0,1]{1}))\/(([1]{1}[9]{1}[9]{1}\d{1})|([2-9]{1}\d{3}))$"; 
    

    У вас пропадет \, и <regex> не может их просмотреть.

    Чтобы указать \ в строке, вам необходимо сбежать, \\.

    Кстати, печать строки является одним из этапов отладки на языках, где нет выделенного литерала RegExp, и конструкция должна выполняться через строку.

  • Вы строите поиск по ^ и $. Он найдет совпадение, если дата сама по себе в строке, и не должно быть даже ведущих или конечных пробелов.

  • У вас много избыточного синтаксиса, например. [1]{1} или. Класс символов с одиночным символом (который не является особым символом в регулярном выражении) может быть удален, то есть 1{1}. И {1}всегда избыточный, то есть [1]{1} можно укоротить до 1.

  • / не требуется экранирование, как в строковом литерале, так и в регулярном выражении.

  • Закрепление синтаксические проблемы выше и удалить ^ и $:

    "[0,1]?\\d/(([0-2]?\\d)|(3[0,1]))/((199\\d)|([2-9]\\d{3}))" 
    
  • [0,1] К, вы, вероятно, хотите [01]. Если вы хотите совместить либо символ A, либо B, просто поместите их рядом друг с другом в класс символов [AB]. Ваш [0,1] также будет соответствовать запятой ,.

  • Вы можете опустить () в ([0-2]?\\d), (3[0,1]). То же самое за год. Внешней группы захвата достаточно.

  • Применение 2 пункта выше:

    "[01]?\\d/([0-2]?\\d|3[01])/(199\\d|[2-9]\\d{3})" 
    

Регулярное выражение должно работать, когда вы хотите извлечь данные, но не так хорошо, если вы хотите использовать его для проверки. Я не знаю, почему вы ограничиваете год с 1990 по 9999 год, но это, вероятно, ваша бизнес-логика.

+0

Большое вам спасибо за подробное объяснение. Я не знаю, как писать регулярные выражения, это мой первый раз, используя один, и я ничего не знаю о них. Я просто скопировал это выражение из Google. Знаете ли вы о каких-либо ресурсах, где я могу узнать о них. Кроме того, я не хочу, чтобы его ограничивали с 1990 по 9999 годы, как бы я это исправил? Еще раз спасибо. –

+0

@DaveCribbs: Какой диапазон вы хотите в течение года? Что касается ресурсов, то в случае C++ проверьте ECEx/JavaScript RegExp (так как на нем используется регулярное выражение на C++) ** сначала **, затем проверьте http://stackoverflow.com/questions/22937618/reference-what-does -это-regex-mean/22944075 # 22944075, если вам нужно более глубокое объяснение. – nhahtdh

+0

Есть ли способ заставить его принять любой год или он должен иметь спецификацию? –

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