C++ 正则表达式

//1.当函数返回string时候的注意点:
string Fun()
{
        return string("szn");
}

const char* pStr = Fun().c_str();
//如上代码,pStr = "" 而非 "szn",原因:返回的string变量被析构了


//2.正则表达式组件:
regex:用于表示一个正则表达式
regex_match:将一个字符序列与一个正则表达式匹配
regex_search:寻找第一个与正则表达式匹配的子序列
regex_replace:使用给定格式替换一个正则表达式
sregex_iterator:迭代器适配器,调用regex_search来遍历一个string中所有匹配的字串
smatch:容器类,保存在string中搜索的结果
ssub_match:string中匹配的子表达式的结果

regex文件中的一些定义:
typedef basic_regex<char> regex;
typedef basic_regex<wchar_t> wregex;
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_search, regex_match的参数(返回值均为bool类型):
seq, m, r, mft
seq, r, mft
seq:字符序列
m:与seq兼容的match对象
r:一个正则表达式
mtf:可选值,用来保存匹配结果的相关细节

输入类型与正则表达式库对应关系:
string                  regex, smatch, ssub_match, sregex_iterator
const char*             regex, cmatch, csub_match, cregex_iterator
wstring                 wregex, wsmatch, wssub_match, wsregex_iterator
const wchar_t*  wregex, wcmatch, wcsub_match, wcregex_iterator

regex(和 wregex)选项:
regex r(re, f):f为可选参数,默认为 regex::ECMAScript,此标志控制regex对象的处理过程
        f:
        regex::icase            忽略大小写
        regex::nosubs           不保存匹配的子表达式
        regex::optimize         执行速度优于构造速度
        regex::ECMAScript       
        regex::basic
        regex::extended
        regex::awk
        regex::grep
        regex::egrep
=:赋值操作
        regex re;
        re = "[123]";
r.assign(re, f):功能等同于赋值操作
r.mark_count():r中表达式数目
r.flags():返回r的标志集


//3.regex_search使用示例:
regex re("[[:alpha:]]*[^c]ei[[:alpha:]]*");
cmatch cm;
if (regex_search("receipt freind theif recive", cm, re))
{
        const char* pStrC = cm.str().c_str();   //pStrC = ""
        string str = cm.str();                                  //str = "freind"
}

regex re("[a-z]+", regex::icase);
smatch sm;
string strContent("12 3456ABCabc7 89");
if (regex_search(strContent, sm, re))
{
        string str = sm.str();                                  //str = "ABCabc"
}
ssub_match subMatch = sm[0];
string str = subMatch;                                          //str = "ABCabc"


//4.
A:一个正则表达式的语法是否正确是在运行时候进行解析的
B:若编写的正则表达式有误,则运行时,标准库会抛出一个regex_error的异常
C:正则表达式的编译可能会是一个非常慢的操作,所以要避免创建很多没必要的regex变量
try
{
        regex re("[");
}
catch (std::regex_error e)                                      //e = {_Err=error_brack }
{
        printf("");                                                             //运行至此
}

enum error_type
{       // identify error
        error_collate,
        error_ctype,
        error_escape,
        error_backref,
        error_brack,
        error_paren,
        error_brace,
        error_badbrace,
        error_range,
        error_space,
        error_badrepeat,
        error_complexity,
        error_stack,
        error_parse,
        error_syntax
};

//5.sregex_iterator
A:sregex_iterator it(b, e, r); 一个 sregex_iterator 遍历迭代器表示string,调用 regex_search 将 it 定位到输入中第一个匹配的位置
B:sregex_iterator end; sregex_iterator 的尾后迭代器
C:*it it-> 根据最后一个调用 regex_search 的结果,返回一个 smatch 对象的指针或引用
D:++it it++ 从输入序列当前位置开始调用 regex_search

使用示例
string str = "abc 123 sdfd4567sdf 456 sdf";
regex re(" ([0-9]+) ");
smatch sm;
vector<string> vecStr[2];

for (sregex_iterator it(str.begin(), str.end(), re), ItEnd; it != ItEnd; ++it)
{
        vecStr[0].emplace_back(it->str()); 
        vecStr[1].emplace_back(it->str(1));
}
//vecStr[0] = [2](" 123 "," 456 ")
//vecStr[1] = [2]("123","456")


//6.
A:正则语法通常用括号表示子表达式


//7.regex_replace使用的简单示例
regex re("[0-9]+");
string str("abc123efg456");
string str0 = regex_replace(str, re, string("Test"));                                                                                           //str0 = "abcTestefgTest"
string str1 = regex_replace(str, re, string("Test"), std::regex_constants::format_first_only);          //str1 = "abcTestefg456"

string str("123abc45_abc_67");
regex re("([0-9]+)([a-z]+)([0-9]+)");
std::smatch sm;
if (regex_search(str, sm, re))
{
        string str0 = sm.str(0);                //str0 = "123abc45"
        string str1 = sm.str(1);                //str1 = "123"  
        string str2 = sm.str(2);                //str2 = "abc"
        string str3 = sm.str(3);                //str3 = "45"
}
string strRe0 = std::regex_replace(str, re, string("szn"));             //strRe0 = "szn_abc_67"
string strRe1 = std::regex_replace(str, re, string("$1szn$3")); //strRe1 = "123szn45_abc_67"

match_default = 0x0000,         //默认
match_not_bol = 0x0001,         //不将首字符作为行首处理
match_not_eol = 0x0002,         //不将尾字符作为行尾处理
match_not_bow = 0x0004,         //不将首字符作为单词首处理
match_not_eow = 0x0008,         //不将尾字符作为单词尾处理
match_any = 0x0010,                     //若存在多个匹配,则返回任意一个匹配
match_not_null = 0x0020,        //不匹配任何空序列
match_continuous = 0x0040,      //匹配必须从输入的首字符开始
match_prev_avail = 0x0100,      //输入序列包含第一个匹配之前的内容
format_default = 0x0000,        //用ECMAScript规则替换字符串
format_sed = 0x0400,            //用POXIS sed规则替换字符串
format_no_copy = 0x0800,        //不输出输入部分中未匹配的部分
format_first_only = 0x1000,     //只替换子表达式第一次出现的位置


//8.regex_match使用示例
regex re0("[0-9]+");
regex re1("[0-9a-z]+");
string str("abc123");
bool nRe0 = regex_match(str, re0);      //nRe0 = false
bool nRe1 = regex_match(str, re1);      //nRe1 = true

regex_match 必须匹配被分析串的全部,若不匹配返回 false ,否则返回 true