目录
1. 正则表达式的语法
参考:https://www.runoob.com/regexp/regexp-syntax.html
注意:Java中可以使用自定义分组,非常方便,C++中貌似不支持自定义分组,需要自己实现逻辑,在使用过程中,我暂时是用的二次匹配策略来实现Java中自定义分组捕获的功能。
2. 正则表达式的三个常用函数或功能
1). regex_match(全文匹配)
要求整个字符串符合匹配规则,返回bool类型
string str = "Hello_2018";
smatch result;
regex pattern("(.{5})_(\\d{4})"); //匹配5个任意单字符 + 下划线 + 4个数字
if (regex_match(str, result, pattern))
{
cout << result[0] << endl; //完整匹配结果,Hello_2018
cout << result[1] << endl; //第一组匹配的数据,Hello
cout << result[2] << endl; //第二组匹配的数据,2018
cout<<"结果显示形式2"<<endl;
cout<< result.str() << endl; //完整结果,Hello_2018
cout<< result.str(1) << endl; //第一组匹配的数据,Hello
cout << result.str(2) << endl; //第二组匹配的数据,2018
}
//遍历结果
for (int i = 0; i < result.size(); ++i)
{
cout << result[i] << endl;
}
result[]与result.str()这两种方式能够获得相同的值,数组用起来更方便。
在匹配规则中,以括号()的方式来划分组别,实例中的规则共有两个括号,所以共有两组数据。
2). regex_search (搜索)
search是搜索匹配,即搜索字符串中存在符合规则的子字符串。
match和search的比较
cout << regex_match("123", regex("\\d")) << endl; //结果为0
cout << regex_search("123", regex("\\d")) << endl; //结果为1
实例
string str = "Hello 2018, Bye 2017";
smatch result;
regex pattern("\\d{4}"); //匹配四个数字
//迭代器声明
string::const_iterator iterStart = str.begin();
string::const_iterator iterEnd = str.end();
string temp;
while (regex_search(iterStart, iterEnd, result, pattern))
{
temp = result[0];
cout << temp << " ";
iterStart = result[0].second; //更新搜索起始位置,搜索剩下的字符串
}
输出结果:2018 2017
补充
//#include "regex.hpp"
#include <regex>
#include <string>
#include <vector>
#include <iostream>
using namespace std;
int test_regex_match()
{
std::string pattern{ "\\d{3}-\\d{8}|\\d{4}-\\d{7}" }; // fixed telephone
std::regex re(pattern);
std::vector<std::string> str{ "010-12345678", "0319-9876543", "021-123456789" };
/* std::regex_match:
判断一个正则表达式(参数re)是否匹配整个字符序列str,它主要用于验证文本
注意,这个正则表达式必须匹配被分析串的全部,否则返回false;如果整个序列被成功匹配,返回true
*/
for (auto tmp : str) {
bool ret = std::regex_match(tmp.c_str(), re);
if (ret) cout << tmp.c_str() << " can match\n" << endl;
else cout << tmp.c_str() << " can not match\n" << endl;
}
return 0;
}
int test_regex_search()
{
std::string pattern{ "http|hppts://\\w*$" }; // url
std::regex re(pattern);
std::vector<std::string> str{ "http://blog.csdn.net/fengbingchun", "https://github.com/fengbingchun",
"abcd://124.456", "abcd https://github.com/fengbingchun 123" };
/* std::regex_search:
类似于regex_match,但它不要求整个字符序列完全匹配
可以用regex_search来查找输入中的一个子序列,该子序列匹配正则表达式re
*/
for (auto tmp : str) {
bool ret = std::regex_search(tmp, re);
if (ret) cout << tmp.c_str() << " can match" << endl;
else cout << tmp.c_str() << " can not match" << endl;
}
return 0;
}
int test_regex_search2()
{
std::string pattern{ "[a-zA-z]+://[^\\s]*" }; // url
std::regex re(pattern);
std::string str{ "my csdn blog addr is: http://blog.csdn.net/fengbingchun , my github addr is: https://github.com/fengbingchun " };
std::smatch results;
while (std::regex_search(str, results, re)) {
for (auto x : results)
std::cout << x << " ";
std::cout << std::endl;
str = results.suffix().str();
}
return 0;
}
int test_regex_search3()
{
std::string pattern{ "[a-zA-z]+"}; // url
std::regex re(pattern);
std::string str{ "12WE34RT56" };
std::smatch ms;
while (std::regex_search(str, ms, re)) {
for (size_t i = 0; i < ms.size(); ++i)
{
std::cout << "第" << i << "个结果:\"" << ms.str(i) << "\" - ";
std::cout << "起始位置:" << ms.position(i) << "长度" << ms.length(i) << std::endl;
}
str = ms.suffix().str();
}
return 0;
}
int test_regex_replace()
{
std::string pattern{ "\\d{18}|\\d{17}X" }; // id card
std::regex re(pattern);
std::vector<std::string> str{ "123456789012345678", "abcd123456789012345678efgh",
"abcdefbg", "12345678901234567X" };
std::string fmt{ "********" };
/* std::regex_replace:
在整个字符序列中查找正则表达式re的所有匹配
这个算法每次成功匹配后,就根据参数fmt对匹配字符串进行替换
*/
for (auto tmp : str) {
std::string ret = std::regex_replace(tmp, re, fmt);
cout << "src:" << tmp.c_str() << " , dst:" << ret.c_str() << endl;
}
return 0;
}
int test_regex_replace2()
{
// reference: http://www.cplusplus.com/reference/regex/regex_replace/
std::string s("there is a subsequence in the string\n");
std::regex e("\\b(sub)([^ ]*)"); // matches words beginning by "sub"
// using string/c-string (3) version:
std::cout << std::regex_replace(s, e, "sub-$2");
// using range/c-string (6) version:
std::string result;
std::regex_replace(std::back_inserter(result), s.begin(), s.end(), e, "$2");
std::cout << result;
// with flags:
std::cout << std::regex_replace(s, e, "$1 and $2", std::regex_constants::format_no_copy);
std::cout << std::endl;
return 0;
}
int main_1() {
//test_regex_match();
//test_regex_replace();
test_regex_search3();
return 0;
}
对于中文,需要使用宽字符,以下是实现中文的匹配和替换匹配的示例
void init()
{
std::wstring digits = L"[零|一|幺|二|两|三|四|五|六|七|八|九]";
std::wstring digitsWithTen = L"[零|一|幺|二|两|三|四|五|六|七|八|九|十|期]";
slot = L"number";
std::wstring p = L"(?:" + digits + L"{3,}" + digitsWithTen + L"*)";
//p = L"([零|一|幺|二|两|三|四|五|六|七|八|九]{3,}[零|一|幺|二|两|三|四|五|六|七|八|九|十|期]*)";
std::locale loc("");
std::wcout.imbue(loc);
// 表达式选项 - 忽略大小写
std::regex_constants::syntax_option_type fl = std::regex_constants::icase;
// 编译一个正则表达式语句
std::wregex regExpress(p, fl);
pattern = regExpress;
category = NumberCategory::DIGIT;
}
std::wstring translate(std::wstring sentence) {
std::wstring result = L"";
int pre, old_last = 0;
std::wstring key;
DigitMap *digitmap = DigitMap::GetInstance();
// 保存查找的结果
std::wsmatch ms;
// 查找
while (std::regex_search(sentence, ms, pattern))
{
std::wstring value;
key = ms.str(0);
if (category == NUMBER)
{
value = digitmap->convertNumber(key);
}
else
{
value = digitmap->convertDigits(key);
}
result = result + ms.prefix().str() + value;
sentence = ms.suffix().str();
}
//不为空说明至少匹配一个,否则返回空串
if (result != L"")
{
result = result + sentence;
}
return result;
}
其中,尤其需要注意的是smatch中prefix和suffix的用法,分别表示匹配字符串在主串中之前和之后的子串。
3). regex_replace(替换)
replace是替换匹配,即可以将符合匹配规则的子字符串替换为其他字符串。
string str = "Hello_2018!";
regex pattern("Hello");
cout << regex_replace(str, pattern, "") << endl; //输出:_2018,将Hello替换为""
cout << regex_replace(str, pattern, "Hi") << endl; //输出:Hi_2018,将Hello替换为Hi
拓展
除了直接替换外,还有可以用来调整字符串内容(缩短、顺序等)
string str = "Hello_2018!";
regex pattern2("(.{3})(.{2})_(\\d{4})"); //匹配3个任意字符+2个任意字符+下划线+4个数字
cout << regex_replace(str, pattern2, "$1$3") << endl; //输出:Hel2018,将字符串替换为第一个和第三个表达式匹配的内容
cout << regex_replace(str, pattern2, "$1$3$2") << endl; //输出:Hel2018lo,交换位置顺序
$n用于表示第n组匹配数据(组这个概念在文章前面部分提到过),所以我们可以利用这种方式来将字符串的内容进行调整。
regex::icase:匹配时忽略大小写。
3. python中的正则使用
https://www.runoob.com/python/python-reg-expressions.html
4. linux下正则的使用
https://blog.csdn.net/windeal3203/article/details/52930947
5. 帮助网站
附上两个写正则表达式常用到的网站
regexper(显示正则表达式匹配结构)
6. 参考
1. https://blog.csdn.net/qlb7707/article/details/51957415
2. https://blog.csdn.net/qq_34802416/article/details/79307102