Регулярные выражения в С++: использование Boost::Regex

В этой заметке я рассмотрю такую достаточно популярную тему, как использование регулярных выражений. Причем, рассматривать я буду применительно к C++ с использованием библиотеки Boost, которая содержит замечательные средства для их поддержки.

Используемый синтаксис реглярных выражений совпадает с широко известным PCRE (Perl-Compatible Regular Expressions).

Для использования библиотеки необходимо включить заголовочный файл boost/regex.hpp:

#include <boost/regex.hpp>

Сразу стоит отметить, что в отличие от многих других компонентов Boost, этот компонент содержит является скопилированным, и потому требует связывания с соответствующей библиотекой. В частности, для компилятора GCC необходимо при связывании добавлять флаг -lboost_regex.

Простейшее использование

Для того, чтобы определить регулярное выражение для дальнейшего использования, достаточно объявить переменную типа boost::regexp и передать в конструктор текст регялрного выражения. Например:

boost::regexp exp("(\\d{4}[- ]){3}\\d{4}");
Для того, чтобы обрабатывать регулярные выражения Boost предоставляет три основных функции:
  • regex_match - проверка сопоставления выражения строке;
  • regex_search - поиск сопоставлений выражения в строке;
  • regex_replace - замена сопоставлений выражения в строке на заданную подстроку.
В простейшем случае, эти функции используются следующим образом:

bool r1 = boost::regex_match( "what", exp );
bool r2 = boost::regex_search( "where", exp );
std::string r3 = boost::regex_replace( "what", exp, "to" );

Получение результатов сопоставлений

Однако, в функциях regex_match и regex_search часто требуется извлекать дополнительную информацию о сопоставлении. Для этого используются объекты типа boost::match_results<IterType>. Сам match_results является шаблоном, который в качестве аргумента принимает тип итератора для сопоставляемых символов. Однако, использовать его напрямую совсем не обязательно. Boost предоставляет 4 типа, представляющих уже параметризованные варианты match_results:

namespace boost {
typedef match_results<const char*>                  cmatch; // Используется при сопоставлении C-строк
typedef match_results<const wchar_t*>               wcmatch; // Используется при сопоставлении С-строк в Unicode
typedef match_results<std::string::const_iterator>  smatch; // Используется при сопоставлении STL-строк
typedef match_results<std::wstring::const_iterator> wsmatch; // Используется при сопоставлении STL-строк в Unicode
}
match_results содержит следующие методы и операторы для работы с результатами сопоставлений:
  • size() - количество групп сопоставлений;
  • suffix(), prefix() - информация о префиксе и суффиксе сопоставления;
  • [i] - информация об i-й группе сопоставления.
При этом, "информация о" - это объект имеющий следующие поля:
  • first - итератор, указывающий на начало группы сопоставдления;
  • second - итератор, указывающий на конец группы сопоставдления;
  • matched - булево поле, равное true если группа была сопоставлена.
Для получения результатов сопоставления используются варианты функций, принимающие дополнительный аргумент. Например:

boost::cmatch m;

if ( boost::regexp_match( "what", m, exp ) ) {
	int sz = m.size(); // Количество групп сопоставления
	for ( int i = 0; i < sz; ++ i )
		std::cout << std::string( m[i].first, m[i].second ) << std::endl;
}

while ( boost::regexp_search( "waht", m, exp ) ) {
	...
}

Примеры

В качестве первого примера, рассмотрим функцию на C++, которая проверяет, может ли заданная строка являться корректным адресом электронной почты:

#include <string>

#include <boost/regex.hpp>

bool can_be_email( const std::string & s ) {
        static const boost::regex e("[a-zA-Z0-9_\\.]+@([a-zA-Z0-9]+\\.)+[a-zA-Z]{2,4}");
        return boost::regex_match( s, e );
}
Второй пример: извлечение из e-mail имени ящика и домена:

#include <string>
#include <stdexcept>

#include <boost/regex.hpp>

std::pair<std::string,std::string> split_email(  const std::string & s ) {
	static const boost::regex e("([a-zA-Z0-9_\\.]+)@(([a-zA-Z0-9]+\\.)+[a-zA-Z]{2,4})");
	
	boost::smatch m;
	if ( boost::regex_match( s, m, e ) ) {
		return std::make_pair( std::string( m[1].first, m[1].second ), std::string( m[2].first, m[2].second ) );
	} else {
		throw std::runtime_error( "Bad email" );
	}
}

 Подписаться на RSS

 #  #  #  #  #  #  #  #  #  #

Добавить комментарий