突然想写个爬虫,然后发现,如果有正则表达式,会方便些。
C++11提供了Regex类.可以用来完成:
1.Match: 将整个输入拿来比对(匹配)某个正则表达式。
2.Search:查找“与正则表达式吻合”的子序列。
3.Tokenize:正则表达式作为分割器,得到分割器之前的字符串。
4.Replace:将与正则表达式吻合之的子序列替换掉
主要函数有: regex_match(),regex_search(),regex_replace();
主要对象:sregex_iterator,sregex_token_iterator,regex,smatch
例子:
[_[:alpha:]][_[:alnum:]]* 表示,以_或字母开头,后面接着任意个_或字母的组合
[123]?[0-9]\.1?[0-9]\.20[0-9]{2} 表示german format,如 24.12.2010
C++11默认使用 ECMAScript 文法,告诉你怎么构造正则表达式
| 表示式 | 意义 |
| . | newline以外的任何字符 |
| [...] | ...字符中的任何一个 |
| [^...] | ...字符之外的任何一个 |
| [ [:charclass:]] | 指定字符串类charclass中的一个(见下表) |
| \n,\t,\f,\r,\v | 一个newline,tabulator,form feed,carriage return,vertical tab |
| \xhh,\uhhh | 一个十六进制字符或Unicode字符 |
| * | 前一个字符或群组,任意次数 |
| ? | 前一个字符或群组,可有可无 |
| + | 前一个字符或群组,至少一次 |
| {n} | 前一个字符或群组,n次 |
| {n,} | 前一个字符或群组,至少n次 |
| {n,m} | 前一个字符或群组,至少n次,至多m次 |
| ...|... | 在 | 之前或之后的pattern,合并左边和右边,(.|\n)*表示任意字符和任意换行 |
| (...) | 设定群组(group) |
| \1,\2,\3 | 第n个group(第一个group的索引为1) |
| \b | 一个正字词边界,字词的起点或终点,不知道什么意思 |
| \B | 一个负字词的边界,字词的非起点或非终点 |
| ^ | 一行的起点 |
| $ | 一行的终点 |
| 字符类 | 缩写 | 转义 | 效果 |
| [[:alnum:]] | 一个字母或者数字 | ||
| [[:alpha:]] | 一个字母 | ||
| [[:blank:]] | 一个space或者tab | ||
| [[:cntrl:]] | 一个控制字符 | ||
| [[:digit:]] | [[:d:]] | \d | 一个数字 |
| \D | 一个非数字 | ||
| [[:graph:]] | 可打印非空白字符,相当于[[:alnum:][:punct:]] | ||
| [[:lower:]] | 一个小写字母 | ||
| [[:print:]] | 一个可打印字符,包括空白字符 | ||
| [[:punct:]] | 一个标点符号字符,但非space,digit,letter | ||
| [[:space:]] | \s | 一个空白字符 | |
| \S | 一个非空白字符 | ||
| [[:upper:]] | 一个大写字母 | ||
| [[:xdigit:]] | 一个十六进制数字 | ||
| \w | 一个字母、数字或下划线 | ||
| \W | 一个非字母、非数字 |
附上一个测试例子:
#include <regex>
#include <iostream>
#include <string>
#include <iomanip>
#include <algorithm>
using namespace std;
void out(bool b){
cout << ( b? "found" : "not found") << endl;
}
void regex1();
void regex2();
void regex3();
void regex4();
void regex5();
void regex6();
int main(){
//regex1();
//regex2();
//regex3();
//regex4();
//regex5();
//regex6();
string data = "1994-06-25\n"
"2015-09-13\n"
"2015 09 13\n";
smatch m;
regex reg("(\\d{4})[- ](\\d{2})[- ](\\d{2})");
//sregex_iterator pos(data.cbegin(),data.cend(),regex("(\\d{4})[- ](\\d{2})[- ](\\d{2})"));
sregex_iterator pos(data.cbegin(),data.cend(),reg);
sregex_iterator end;
for( ; pos!=end ;pos++){
cout << pos->str() << " ";
cout << pos->str(1) << " " <<pos->str(2) <<" " << pos->str(3) << endl;
}
system("pause");
return 0;
}
/*
* regex_replace(string,reg1,reg2)
* 将reg1匹配到的子串,用reg2替换掉
*/
void regex6(){
string data = "<person>\n"
"<first>Nico</first>\n"
"<last>Josuttis</last>\n"
"</person>\n";
regex reg("<(.*)>(.*)</(\\1)>");
cout << regex_replace(data,reg,"<$1 value=\"$2\"/>") << endl;
string res2;
regex_replace (back_inserter(res2),
data.begin(),data.end(),
reg,
"<$1 value=\"$2\"/>",
regex_constants::format_no_copy
| regex_constants::format_first_only);
cout << res2 << endl;
}
/*
* sregex_token_iteartor 分割器
* 详情看函数输出,比如,通过这个,可以取出下面的名字
*/
void regex5(){
string data = "<person>\n"
"<first>Nico</first>\n"
"<last>Josuttis</last>\n"
"</person>\n";
regex reg("<(.*)>(.*)</(\\1)>");
sregex_token_iterator pos(data.cbegin(),data.cend(),reg,0);
sregex_token_iterator end;
for(; pos!=end;pos++){
cout << "match: "<<pos->str() << endl;
}
cout<< endl;
string names = "nico,jim,helmut,paul,tim,john paul,rita";
regex sep("[ \t\n]*[,;.][ \t\n]*");
sregex_token_iterator p(names.cbegin(),names.cend(),sep,-1);
sregex_token_iterator e;
for(; p!=e;p++){
cout << "name: "<<*p << endl;
}
}
/*
* sregex_iterator 迭代器,通过这样个来遍历所以满足的子串
* 注意传进去的 begin,end 必须是const 所以使用 cbegin()
*/
void regex4(){
string data = "<person>\n"
"<first>Nico</first>\n"
"<last>Josuttis</last>\n"
"</person>\n";
regex reg("<(.*)>(.*)</(\\1)>");
sregex_iterator pos(data.cbegin(),data.cend(),reg);
sregex_iterator end;
for(;pos != end;++pos){
cout << "match: "<< pos->str(0) << endl;
cout << "tag: "<< pos->str(1)<< endl;
cout << "value "<< pos->str(2) << endl;
}
sregex_iterator beg(data.cbegin(),data.cend(),reg);
for_each(beg,end,[](const smatch& m){
cout << "match: "<< m.str() << endl;
cout << "tag: "<< m.str(1)<< endl;
cout << "value "<< m.str(2) << endl;
});
}
/*
* bool regex_search(string , smatch ,regex )
* 对整个字符串,用这个regex进行匹配,找到第一个满足的子串,
* 通过前面的例子,可以发现 m.suffix() 指得是,满足子串后面的,
* 一个字符的索引,所以,通过一个循环,可以不断找出后面满足的
*/
void regex3(){
string data = "<person>\n"
"<first>Nico</first>\n"
"<last>Josuttis</last>\n"
"</person>\n";
regex reg("<(.*)>(.*)</(\\1)>");
auto pos = data.cbegin();
auto end = data.cend();
smatch m;
for(; regex_search(pos,end,m,reg);pos = m.suffix().first){
cout << "match: "<<m.str() << endl;
cout << "tag: "<<m.str(1) << endl;
cout << "value: " << m.str(2) << endl;
cout << "m.prefix(): "<<m.prefix().str() << endl;
cout << "m.suffix(): "<<m.suffix().str() << endl;
}
}
/*
* bool regex_search(string , smatch ,regex )
* 对整个字符串,用这个regex进行匹配,找到第一个满足的子串,
* 下面是通过smatch 获取子串内容的方法,索印对应群组
*/
void regex2(){
string data = "XML tag: <tag-name>the value</tag-name>.";
cout << "data: "<<data << "\n\n";
smatch m;
bool found = regex_search(data,m,regex("<(.*)>(.*)</(\\1)>"));
cout << "m.empty(): "<<boolalpha << m.empty() << endl;
cout << "m.size(): "<<m.size() << endl;
if(found){
cout << "m.str(): "<<m.str() << endl;
cout << "m.length(): "<<m.length()<<endl;
cout << "m.position(): "<<m.position()<<endl;
cout << "m.prefix().str(): "<<m.prefix().str()<< endl;
cout << "m.suffix().str(): "<<m.suffix().str() << endl;
cout << endl;
for(int i = 0;i<m.size();i++){
cout << "m["<<i<<"].str(): " << m[i].str() << endl;
cout << "m.str("<<i << "): " << m.str(i) << endl;
cout << "m.position(" << i << "): "<<m.position(i)<<endl;
}
cout << endl;
cout << "matches:" << endl;
for(auto pos = m.begin();pos!=m.end();pos++){
cout << " "<< *pos << " ";
cout << "(length: " << pos->length() << ")" << endl;
}
}
}
/*
* bool regex_match(string , regex )
* 对整个字符串,用这个regex进行匹配,会匹配最大满足的字符串
*/
void regex1(){
regex reg1("<.*>.*</.*>");
bool found = regex_match("<tag>value</tag>",reg1);
out(found);
regex reg2("<(.*)>.*</\\1>");
found = regex_match("<tag>value</tag>",reg2);
out(found);
regex reg3("<\\(.*\\)>.*</\\1>",regex_constants::grep);
found = regex_match("<tag>value</tag>",reg3);
out(found);
found = regex_match("<tag>value</tag>",regex("<(.*)>.*</\\1>"));
out(found);
cout << endl;
found = regex_match("XML tag: <tag>value</tag>",
regex("<(.*)>.*</\\1>"));
out(found);
found = regex_match("XML tag: <tag>value</tag>",
regex(".*<(.*)>.*</\\1>"));
out(found);
found = regex_search("XML tag: <tag>value</tag>",
regex("<(.*)>.*</\\1>"));
out(found);
found = regex_search("XML tag: <tag>value</tag>",
regex(".*<(.*)>.*</\\1>"));
out(found);
}
来源:https://www.cnblogs.com/cycxtz/p/4804115.html