Regex C++ : 正则表达式(2).

旧时模样 提交于 2020-02-29 16:46:49

既然有了std::basic_regex存储我们的正则表达式了,那我们怎么匹配到的字符串呢?

重点强调: 无论是std::regex_match还是std::regex_search都不能接受一个右值版本的std::basic_string!!!!!

下面我们将介绍:

std::regex_search:检验是否部分字符串匹配给定的正则表达式.

std::regex_match :检验是否整个字符串匹配给定的正则表达式.

  • std::regex_search
//first: 一个指向被匹配字符串开始位置的迭代器.
//last: -个指向被匹配字符串结束位置的迭代器.
//m: 存放匹配的结果.
//e: 存放正则表达式.
//flags: 指出使用哪种正则表达式的语法.
template< class BidirIt,
          class Alloc, class CharT, class Traits >
bool regex_search( BidirIt first, BidirIt last,
                   std::match_results<BidirIt,Alloc>& m,
                   const std::basic_regex<CharT,Traits>& e,
                   std::regex_constants::match_flag_type flags =
                       std::regex_constants::match_default );


//str: 被匹配的C风格的字符串.
//m: 存放匹配结果.
//e: 存放正则表达式.
//flags: 指出使用哪种正则表达式.
template< class CharT, class Alloc, class Traits >
bool regex_search( const CharT* str,
                   std::match_results<const CharT*,Alloc>& m,
                   const std::basic_regex<CharT,Traits>& e,
                   std::regex_constants::match_flag_type flags =
                       std::regex_constants::match_default );

//s: 存放一个被匹配的字符串.
//m: 存放匹配到的结果.
//e: 存放正则表达式.
//flags: 指出使用哪种正则表达式.
template< class STraits, class SAlloc,
          class Alloc, class CharT, class Traits >
bool regex_search( const std::basic_string<CharT,STraits,SAlloc>& s,
                   std::match_results<
                       typename std::basic_string<CharT,STraits,SAlloc>::const_iterator,
                       Alloc
                   >& m,
                   const std::basic_regex<CharT, Traits>& e,
                   std::regex_constants::match_flag_type flags =
                       std::regex_constants::match_default );

//first: 一个指向被匹配字符串开始位置的迭代器.
//last: -个指向被匹配字符串结束位置的迭代器.
//e: 存放正则表达式.
//flags: 指出使用哪种正则表达式.
template< class BidirIt,
          class CharT, class Traits >
bool regex_search( BidirIt first, BidirIt last,
                   const std::basic_regex<CharT,Traits>& e,
                   std::regex_constants::match_flag_type flags =
                       std::regex_constants::match_default );


//str: 被匹配的C风格的字符串.
//e: 存放正则表达式.
//flags: 指出使用哪种正则表达式.
template< class CharT, class Traits >
bool regex_search( const CharT* str,
                   const std::basic_regex<CharT,Traits>& e,
                   std::regex_constants::match_flag_type flags =
                       std::regex_constants::match_default );


//s: 存放一个被匹配的字符串.
//e: 存放正则表达式.
//flags: 指出使用哪种正则表达式.
template< class STraits, class SAlloc,
          class CharT, class Traits >
bool regex_search( const std::basic_string<CharT,STraits,SAlloc>& s,
                   const std::basic_regex<CharT,Traits>& e,
                   std::regex_constants::match_flag_type flags =
                       std::regex_constants::match_default );

//不能接受一个右值的 std::basic_string<CharT>
template< class STraits, class SAlloc,
          class Alloc, class CharT, class Traits >
bool regex_search( const std::basic_string<CharT,STraits,SAlloc>&&,
                   std::match_results<
                       typename std::basic_string<CharT,STraits,SAlloc>::const_iterator,
                       Alloc
                   >&,
                   const std::basic_regex<CharT, Traits>&,
                   std::regex_constants::match_flag_type flags =
                       std::regex_constants::match_default ) = delete;

 

Demo for std::regex_search:

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

int main()
{
	std::basic_regex<char> re("<(.*)>(.*)</(\\1)>");
	std::regex reg("<(.*)>(.*)</(\\1)>");

	/*std::basic_string<char>*/ std::string data = "<person>\n"
		                           "<first>Nico</first>\n"
		                           "<last>Josuttis</last>\n"
		                           "<person\n";

	std::match_results<std::basic_string<char>::const_iterator> result;

	std::basic_string<char>::const_iterator beg = data.cbegin();
	std::basic_string<char>::const_iterator end = data.cend();
	std::smatch result_;
	for (; std::regex_search(beg, end, result_, re); beg = result_.suffix().first) {
		std::cout << "------------------" << std::endl;
		std::cout << "length: " << result_.length() << std::endl;
		std::cout << result_.str() << std::endl;
	}

	return 0;

}
  • std::regex_match

//检验这两个iterator范围内的字符串是否符合正则表达式
//另外我们可以给std::match_result提供allocator!
template< class BidirIt,class Alloc, class CharT, class Traits >
bool regex_match( BidirIt first, BidirIt last,
                  std::match_results<BidirIt,Alloc>& m,
                  const std::basic_regex<CharT,Traits>& e,
                  std::regex_constants::match_flag_type flags = std::regex_constants::match_default );

//检验这两个iterator范围内的字符串是否符合正则表达式.
//注意: 不用提供 std::match_result!
//不可以提供allocator.
template< class BidirIt, class CharT, class Traits >
bool regex_match( BidirIt first, BidirIt last,
                  const std::basic_regex<CharT,Traits>& e,
                  std::regex_constants::match_flag_type flags = std::regex_constants::match_default );

//接受一个C风格的字符串.
//并可以为std::match_result提供allocator!
template< class CharT, class Alloc, class Traits >
bool regex_match( const CharT* str,
                  std::match_results<const CharT*,Alloc>& m,
                  const std::basic_regex<CharT,Traits>& e,
                  std::regex_constants::match_flag_type flags = std::regex_constants::match_default );

//接受一个std::basic_string(可提供allocator)
//另外也可以为std::mathch_result提供allocator!
template< class STraits, class SAlloc, class Alloc, class CharT, class Traits >
bool regex_match( const std::basic_string<CharT,STraits,SAlloc>& s,
                  std::match_results<typename std::basic_string<CharT,STraits,SAlloc>::const_iterator, Alloc>& m,
                  const std::basic_regex<CharT,Traits>& e,
                  std::regex_constants::match_flag_type flags = std::regex_constants::match_default );

//接受一个C风格的字符串可不提供任何allocator!
//注意: 可以不提供std::match_results.
template< class CharT, class Traits >
bool regex_match( const CharT* str,
                  const std::basic_regex<CharT,Traits>& e,
                  std::regex_constants::match_flag_type flags =
                      std::regex_constants::match_default );

//接受一个std::basic_string(可以提供allocator).
//注意: 不用提供std::match_results.
template< class STraits, class SAlloc, class CharT, class Traits >
bool regex_match( const std::basic_string<CharT, STraits, SAlloc>& s,
                  const std::basic_regex<CharT,Traits>& e,
                  std::regex_constants::match_flag_type flags = std::regex_constants::match_default );

//我们不能指定一个右值版本的std::basic_string作为被匹配的对象
//该版本是被delete了的.
template< class STraits, class SAlloc, class Alloc, class CharT, class Traits >
bool regex_match( const std::basic_string<CharT,STraits,SAlloc>&&,
                  std::match_results<typename std::basic_string<CharT,STraits,SAlloc>::const_iterator, Alloc>&,
                  const std::basic_regex<CharT,Traits>&,
                  std::regex_constants::match_flag_type flags =
                      std::regex_constants::match_default ) = delete;

应该也注意到了上面所有版本的函数最后都指定了一个flag.

该flag是定义在std::regex_constants这个namespace中的一个enum.

std::regex_constants::match_default : 使用默认的方式匹配.

std::regex_constants::match_not_bol : 第一个字符不匹配(不匹配'^').

std::regex_constants::match_not_eol : 最后一个字符不匹配(不匹配'$').

std::regex_constants::match_not_bow : 第一个字符不匹配(转义序列'\b'被当作首字符不匹配).

std::regex_constants::match_not_eow : 最后一个字符不匹配(转义序列'\b'被当作尾字符不匹配).

std::regex_constants::match_any : 如果存在多余一个匹配,则可返回任意一个匹配.

std::regex_constants::match_not_null : 不匹配任何空序列.

std::regex_constants::continuous : 只试图匹配从第一个字符开始的子序列.

std::regex_constants::match_prev_avail : 第一个字符的前一个有效位置(造成忽略match_not_bol和match_not_bow).

 

  • replace flag:

std::regex_constants::format_default : 用ECMAScript规则替换字符串.

std::regex_constants::format_se : 用POSIX set 规则替换字符串.

std::regex_constants::format_no_copy : 对未匹配的字符(或字符串)不予复制.

std::regex_constants::format_first_only : 只替换给定string中第一次匹配的地方.

 

正则表达式不仅用在我们希望查找一个给定序列的时候,还可以用在我们想要将找到的序列替换为另一个序列的时候.

重点注意: 替换操作都是在原字符串的拷贝上进行的,且std::regex_replace不用指定std::match_results;

  • std::regex_replace

//OutputIt: 可以是std::ostream_iterator, 也可以是std::ostreambuf_iterator.
//BidIt first, last: 一对std::basic_string的迭代器,用于被正则表达式匹配.
//std::basic_regex我们指定的正则表达式.
//fmt: 我们指定的替换格式(它有一套替换规则稍后介绍)
//flag: 替换规则前面已经介绍了.
//返回: OutputIt类型.
template< class OutputIt, class BidirIt, class Traits, class CharT, class STraits, class SAlloc >
OutputIt regex_replace( OutputIt out, BidirIt first, BidirIt last,
                        const std::basic_regex<CharT,Traits>& re,
                        const std::basic_string<CharT,STraits,SAlloc>& fmt,
                        std::regex_constants::match_flag_type flags = std::regex_constants::match_default );
	

//OutputIt: 同上.
//BiddirIt: 同上.
//std::basic_regex: 同上.
//fmt: 通过C风格的字符串指定替换格式.
//flag: 同上.
//返回: OutputIt类型.
template< class OutputIt, class BidirIt, class Traits, class CharT >
OutputIt regex_replace( OutputIt out, BidirIt first, BidirIt last,
                        const std::basic_regex<CharT,Traits>& re,
                        const CharT* fmt,
                        std::regex_constants::match_flag_type flags = std::regex_constants::match_default );

//std::basic_string:指定被匹配的字符串.(可指定allocator)
//std::basic_regex: 指定正则表达式.
//fmt(std::basic_string):指定替换格式.(可指定allocator).
//flag: 指定替换规则.
//返回: std::basic_string类型.
template< class Traits, class CharT, class STraits, class SAlloc, class FTraits, class FAlloc >
std::basic_string<CharT,STraits,SAlloc>
    regex_replace( const std::basic_string<CharT,STraits,SAlloc>& s,
                   const std::basic_regex<CharT,Traits>& re,
                   const std::basic_string<CharT,FTraits,FAlloc>& fmt,
                   std::regex_constants::match_flag_type flags = std::regex_constants::match_default );

//std::basic_string: 指定被匹配的字符串(可指定allocator).
//std::basic_regex: 指定正则表达式.
//fmt: 通过C风格的字符串指定替换格式.
//flag: 同上.
//return: 返回一个std::basic_string.
template< class Traits, class CharT, class STraits, class SAlloc >
std::basic_string<CharT,STraits,SAlloc> regex_replace( const std::basic_string<CharT,STraits,SAlloc>& s,
                   const std::basic_regex<CharT,Traits>& re,
                   const CharT* fmt,
                   std::regex_constants::match_flag_type flags = std::regex_constants::match_default );

//s: 通过C风格的字符串指定被匹配的字符串.
//re: 指定正则表达式.
//fmt: 指定替换格式.(可指定allocator).
//flag: 同上.
template< class Traits, class CharT, class STraits, class SAlloc >
std::basic_string<CharT> regex_replace( const CharT* s,
                   const std::basic_regex<CharT,Traits>& re,
                   const std::basic_string<CharT,STraits,SAlloc>& fmt,
                   std::regex_constants::match_flag_type flags = std::regex_constants::match_default );

//s:通过C风格的字符串指定被匹配的字符串.
//re: 指定正则表达式.
//fmt: 通过C风格的字符串指定替换格式.
//flag: 同上.
template< class Traits, class CharT >
std::basic_string<CharT> regex_replace( const CharT* s,
                   const std::basic_regex<CharT,Traits>& re,
                   const CharT* fmt,
                   std::regex_constants::match_flag_type flags =
                       std::regex_constants::match_default );

Demo for std::regex_replace:

#include <iostream>
#include <regex>
#include <string>
#include <utility>
#include <iterator>

int main()
{
	std::basic_string<char> data = "<person>\n"
		"<first>Nico</first>\n"
		"<last>Josuttis</last>\n"
		"</person>\n";

	std::basic_regex<char> regex("<(.*)>(.*)</(\\1)>");
	std::ostream_iterator<char> outPut(std::cout);
	std::basic_string<char>::const_iterator pos{ data.cbegin() };
	std::basic_string<char>::const_iterator end{ data.cend() }; 

	
	std::basic_string<char> format{ "<$1 value=\"$2\"/>" };
	std::cout << "----------------------" << std::endl;
	std::regex_replace(outPut, pos, end, regex, std::string("<$1 value=\"$2\"/>"));
	std::cout << "--------" << format << std::endl;

	std::cout << "----------------------" << std::endl;
	pos = data.cbegin();
	end = data.cend();
	std::basic_string<char> container;
	std::regex_replace(std::back_inserter(container), pos, end, regex, std::string("<$$ value=\"$2\"/>"));
	std::cout << container << std::endl;

	std::cout << "-----------------------" << std::endl;
	pos = data.cbegin();
	end = data.cend();
	std::basic_string<char> containerTwo;
	//std::regex_replace(std::inserter(container, containerTwo.begin()), pos, end, regex, std::string("<$$  $‘  $' $$1 $$2>"));
	std::regex_replace(std::back_inserter(containerTwo), pos, end, regex, std::string("<$&>"));

	for (const auto& c : containerTwo) {
		std::cout << c;
	}

	return 0;
}

 

接着我们来看一直 format的语法,在上面的例子中我们指定format的格式为: std::string("<$1 value=\"$2\"/>");

注意到我们使用了 $1 和 $2,其中$1代表正则表达式从data中匹配到的第一个符合正则表达式的第一个子串, $2代表从正则表达式中匹配到的第二个子串.

因此std::regex_replace(itr, pos, end, regex, format)的就是在format的副本的基础上进行替换. 比如:该表达式匹配到的第一个string为: <first>Nico</first> 其中的 first为第一个子串,Nico为第二个子串,</first>中的first为第三个子串. $1被替换为: first, $2被替换为:Nico.

我们来看一下 format的语法:

$& 匹配到的字符串.

$n 匹配到的字符串的第n个子串.

$' 匹配到的字符串的前缀.

$' 匹配到的字符串的后缀.

$$ 字符$.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!