首先不论在window下还是linux下,你要通过c/c++使用正则表达式,你就必须包含所需的头文件regex
,里面包含了所需的函数,一般的第一步需要确定要匹配的模式pattern,使用regex类型进行定义regex pattern("要匹配的正则表达式模式")
,其次一般的常用操作就是灵活的运用regex_match,regex_search,regex_replace
这三个函数,后面还有几个用的不太多的函数regex_iterator
后续会介绍:
regex_match的相关及举例
原型大致为:
bool regex_match (const basic_string<charT,ST,SA>& s,
const basic_regex<charT,traits>& rgx,
regex_constants::match_flag_type flags = regex_constants::match_default);
/**
第一个参数s为:需要用正则表达式去匹配的字符串,简言之就是要处理的字符串。
第二个参数rgx为:为一个basic_regex的一个对象,也就是你要进行匹配的模式,用正则字符串表示,其声明为:
(1)typedef basic_regex<char> regex;//正常字符处理(常用)
(2)typedef basic_regex<wchar_t> wregex;//宽字符处理
第三个参数flags是控制第二个参数如何去匹配,第三个参数处可以设置一个或多个常量去控制,一般设置有默认值
返回值为:如果匹配成功,返回True,否则返回False
*/
/*
此为匹配字符串"wdw9078798asadada",是否满足匹配正则表达式所要求的条件,regex{ "[A-Z]{1,3}.*"}:目的是匹配由1个到三个字母开头的字符串,匹配成功时返回true,否则返回false
*/
status = regex_match("wdw9078798asadada", regex{ "[a-z]{1,3}.*"}); //第三个参数为忽略大小写
if (status == true) {
printf("匹配成功!\n");
}
else {
printf("匹配失败!\n");
}
//结果为匹配成功!
当然在regex定义时,可以指定第二个参数类型flag_type为控制regex的属性,构造函数声明如下:
explicit basic_regex(
const basic_string<_Elem, _STtraits, _STalloc>& _Str,
flag_type _Flags = regex_constants::ECMAScript)
第一参数不用说,就是指定一个字符串,为要匹配的正则式,第一个参数为指定属性,之前已经用到的一个为regex_constants::icase,表示忽略大小写进行匹配,也可以写成regex::icase,但源码中为regex_constants::?这种形式,所以采用这种写法,其中的声明还有:
//来自regex中的声明
static constexpr flag_type icase = regex_constants::icase;//忽略大小写
static constexpr flag_type nosubs = regex_constants::nosubs;//子无表达式,
static constexpr flag_type optimize = regex_constants::optimize;//优化匹配,匹配效率优于构造regex对象的效率。
static constexpr flag_type collate = regex_constants::collate;//区域敏感性
static constexpr flag_type ECMAScript = regex_constants::ECMAScript;//默认的语法
static constexpr flag_type basic = regex_constants::basic;//基础的posix语法
static constexpr flag_type extended = regex_constants::extended;//扩展posix语法
static constexpr flag_type awk = regex_constants::awk;
static constexpr flag_type grep = regex_constants::grep;
static constexpr flag_type egrep = regex_constants::egrep;
英文解释如下(来自c++ reference):似乎最后的六个都跟语法有关,不纠结了,英文水平有限
举例:执行结果与上一个结果相同
status = regex_match("wdw9078798asadada", regex{ "[A-Z]{1,3}.*",regex_constants::icase}); //第三个参数为忽略大小写
if (status == true) {
printf("匹配成功!\n");
}
else {
printf("匹配失败!\n");
}
regex_search的相关及举例
bool regex_search (const basic_string<charT,ST,SA>& s,
const basic_regex<charT,traits>& rgx,
regex_constants::match_flag_type flags = regex_constants::match_default);
//参数含义与regex_match一致,此方法不返回匹配成功的字符串,只是确定里面是否有满足正则式的字句
bool regex_search (const basic_string<charT,ST,SA>& s,
match_results<typename basic_string<charT,ST,SA>::const_iterator,Alloc>& m,
const basic_regex<charT,traits>& rgx,
regex_constants::match_flag_type flags = regex_constants::match_default);
//其他参数含义一样,多了一个m参数,其含义为此处为一个match_results的类型,其作用是存储匹配的结果或者满足子表达式匹配的结果,返回结果为一个迭代器
直接上例子可能比较好理解一些:
//此程序的regex为regex("[0-9]{2}[a-z]{1,4}[0-9]{2}")
smatch result;
string str1("i89love78you,mrsLu");
bool sta = regex_search(str1, result, regex("[0-9]{2}[a-z]{1,4}[0-9]{2}"));
for (auto it : result) {
cout << it.str() << endl;
}
/*结果:
89love78
*/
//此程程序中的regex为regex("([0-9]{2})([a-z]{1,4})([0-9]{2})")注意中间有括号和没有括号的区别
smatch result;
string str1("i89love78you,mrsLu");
bool sta = regex_search(str1, result, regex("([0-9]{2})([a-z]{1,4})([0-9]{2})"));
for (auto it : result) {
cout << it.str() << endl;
}
/*当有子表达式匹配时,访问匹配结果中的存储为:
第一个存储的结果为满足整个正则匹配式的字符串,从第二个开始,依次存储从左向右的每个圆括号中的匹配式的结果,所以可以进行以下访问:
cout << result[0] << endl; //输出89love78
cout << result.str(0) << endl; //输出89love78
二者等效,
cout << result.str(1) << endl; //输出89
cout << result.str(2) << endl; //输出love
cout << result.str(3) << endl; //输出78
*/
/*结果:
89love78
89
love
78
*/
从以上两个程序结果可以看出,smatch存储的结果为以()为子匹配式进行匹配,在某些时候这种方式可以起到非常大的作用。
当然regex_results对象有两个方法suffix()和prefix()分别显示的为匹配结果的后缀和前缀,上述的匹配结果进行调用有如下信息:
smatch result;
string str1("i89love78you,mrsLu");
bool sta = regex_search(str1, result, regex("[0-9]{2}[a-z]{1,4}[0-9]{2}"));
cout << "后缀为:"<<result.suffix().str() << endl <<"前缀为:"<< result.prefix().str() << endl;
/*结果:
后缀为:you,mrsLu
前缀为:i
*/
regex_replace的相关及举例
regex_replace可以查找匹配正则表达式的字符串并使用其它格式来替换,可以是自己想要替换的普通字符串,也可以是$指定
原型声明:
template <class traits, class charT, class ST, class SA>
basic_string<charT,ST,SA> regex_replace (const basic_string<charT,ST,SA>& s,
const basic_regex<charT,traits>& rgx,
const charT* fmt,
regex_constants::match_flag_type flags = regex_constants::match_default);
//第一个参数s表示要被操作的字符串对象
//第二个参数rgx为匹配正则表达式
//第三个参数fmt为以何种方式进行替换
//第四个参数flags为一种方式,代表怎样去替换
//返回值为:如果匹配成功返回已经替换成功的字符串,否则匹配失败,返回原字符串
第三个参数的设置如下表(来自c++ reference)其中(第三个为$`,第四个为$’):
第四个参数的设置常量如下表(来自c++ reference)这些常量全都在regex_contants命名空间中有声明:
举例:
regex pattern("([0-9]{4})-([0-9]{2})-([0-9]{2})");
regex r(pattern);
string date = "日期为:2020-08-04 2020-05-30";
cout << regex_replace(date, r, "$1.$2.$3") << endl;
/*结果:
日期为:2020.08.04 2020.05.30
*/
当然,也可以设置regex_replace第四那个参数,设置将字符串中没有被匹配的部分不输出
cout << regex_replace(date, r, "$1.$2.$3",regex_contants::format_no_copy) << endl;
//输出为2020.08.04 2020.05.30
最常使用的为进行普通字符串的替代
//将字符串中的大写字母换为_
regex patt("[A-Z]");
string s = "www.asxWscnsj.com";
cout<<regex_replace(s, patt, "_");
//执行结果www.asx_scnsj.com
match_results的相关
typedef match_results<const char*> cmatch;
typedef match_results<const wchar_t*> wcmatch;
typedef match_results<string::const_iterator> smatch;(常用)
typedef match_results<wstring::const_iterator> wsmatch;
上面为regex头文件中的宏声明,常用的为smatch,例子见regex_search栏
regex_error的相关及举例
class regex_error : public runtime_error { /* ... */ };
由此可见,该异常类继承自runtime_error类。
异常描述:
此异常类型的对象由正则表达式库的元素引发。
它继承了标准异常runtime_error,并有一个特殊的公共成员函数,它根据引发它的错误的类型返回regex_constants::error_type的特定代码:
具体如下(0-12):
try {
std::regex myregex("*");
}
catch (std::regex_error& e) {
std::cerr << "error code:"<<e.code() << ":" << e.what();
}
/*
error code:10:regex_error(error_badrepeat): One of *?+{ was not preceded by a valid regular expression.
*/
regex_iterator的相关及举例
构造方法:
无参构造函数:regex_iterator();
拷贝构造函数:regex_iterator (const regex_iterator& rit)
初始化构造函数:regex_iterator ( BidirectionalIterator first,
BidirectionalIterator last,
const regex_type& rgx,
regex_constants::match_flag_type flags = regex_constants::match_default);
初始化构造函数的第四个参数与regex_replace的第四个参数的含义一样,复制选项也一样,可参考上述文章
(来源:c++ reference)
std::string s ("this subject has a submarine as a subsequence");
std::regex e ("\\b(sub)([^ ]*)"); // matches words beginning by "sub",后跟非空白字符,遇到空格会终止
std::regex_iterator<std::string::iterator> rit ( s.begin(), s.end(), e );
std::regex_iterator<std::string::iterator> rend;
while (rit!=rend) {
std::cout << rit->str() << std::endl;
++rit;
}
/*
输出为:
subject
submarine
subsequence
*/
由上述的代码例子粗略可知:初始化构造函数的第一二个参数分别为要处理字符串的迭代器的开始(begin)和结束(end),第三个参数为正则式,第四个参数根据具体情况来选择,一般为默认。