C/C++ 中常用的正则表达式库有:
- GNU Regex Library
- Boost.Regex
- PCRE
- PCRE++
这四个库中,后面两个是有关系,其它都是各自己独立的,是不同的实现。
GNU Regex Library
GNU Regex Library 是glibc(GNU C Library)的一部分,它提供与POSIX标准兼容的正则表达式匹配的接口。
更多:http://www.wuzesheng.com/?p=929
PCRE, PCRE++
PCRE (Perl Compatible Regular Expressions)是与 Perl 中正则表达式相兼容的一个正则表达式库。
PCRE++是一个对PCRE库的C++封装,它提供了更加方便、易用的C++接口。
更多:http://www.wuzesheng.com/?p=994
Boost.Regex
boost::regex 为 C++ 提供了完整的正则表达式支持
表达式语法
一般规则
符号 | 解释 |
---|
. | 除换行符以外的所有字符。 | ^ | 字符串开头。 | $ | 字符串结尾。 | \d,\w,\s | 匹配数字、字符、空格。 | \D,\W,\S | 匹配非数字、非字符、非空格。 | [abc] | 匹配 a、b 或 c 中的一个字母。 | [a-z] | 匹配 a 到 z 中的一个字母。 | [^abc] | 匹配除了 a、b 或 c 中的其他字母。 | aa|bb | 匹配 aa 或 bb。 | ? | 0 次或 1 次匹配。 | * | 匹配 0 次或多次。 | + | 匹配 1 次或多次。 | {n} | 匹配 n次。 | {n,} | 匹配 n次以上。 | {m,n} | 最少 m 次,最多 n 次匹配。 | (expr) | 捕获 expr 子模式,以 \1 使用它。 | (?:expr) | 忽略捕获的子模式。 | (?=expr) | 正向预查模式 expr。 | (?!expr) | 负向预查模式 expr。 |
懒惰限定符
代码/语法 | 说明 |
---|
*? | 重复任意次,但尽可能少重复 | +? | 重复1次或更多次,但尽可能少重复 | ?? | 重复0次或1次,但尽可能少重复 | {n,m}? | 重复n到m次,但尽可能少重复 | {n,}? | 重复n次以上,但尽可能少重复 |
编译
编译介绍:http://www.wuzesheng.com/?p=965
在 C++11 以后,Boot.Regex 已被接收为C++0x标准库 。
因此现在只需要加入 regex 头文件,就可以在 std namespace 中使用它们的类和方法了。
#include <boost/regex.hpp>
#include <string>
#include <iostream>
int main()
{
std::string s = "Boost Libraries";
boost::regex expr{"\\w+\\s\\w+"};
std::cout << std::boolalpha << boost::regex_match(s, expr) << '\n';
}
使用
参考:https://theboostcpplibraries.com/boost.regex#ex.regex_01
在Boost.Regex 中,两个最重要的类是 boost::regex 和 boost::smatch ,前者定义正则表达式,后者保存搜索结果。
namespace boost{
typedef match_results<const char*> cmatch;
typedef match_results<const wchar_t*> wcmatch;
typedef match_results<std::string::const_iterator> smatch;
typedef match_results<std::wstring::const_iterator> wsmatch;
}
在Boost.Regex 中,提供了三个方法(function)来使用查找(search)字符串:
boost::regex_match() boost::regex_search() boost::regex_replace()
搜索 boost::regex_match()
官方文档 - https://www.boost.org/doc/libs/1_80_0/libs/regex/doc/html/boost_regex/ref/regex_match.html
#include <boost/regex.hpp>
#include <string>
#include <iostream>
int main()
{
std::string s = "Boost Libraries";
boost::regex expr{"\\w+\\s\\w+"};
std::cout << std::boolalpha << boost::regex_match(s, expr) << '\n';
}
boost::regex_match() 当匹配到字符串会返回 true
搜索 boost::regex_search()
#include <boost/regex.hpp>
#include <string>
#include <iostream>
int main()
{
std::string s = "Boost Libraries";
boost::regex expr{"(\\w+)\\s(\\w+)"};
boost::smatch what;
if (boost::regex_search(s, what, expr))
{
std::cout << what[0] << '\n';
std::cout << what[1] << "_" << what[2] << '\n';
}
}
boost::regex_search() 需要一个 boost::smatch 作为参数,来保存匹配结果
结果可以直接迭代
optional<std::vector<string>> regex_match(const string target ,const string &pattern )
{
boost::regex reg(pattern);
boost::smatch sm;
std::vector<string> res;
if ( boost::regex_search(target,sm,reg)) {
for (auto str : sm)
res.push_back(str);
return res;
}
return {};
}
替换 boost::regex_replace()
#include <boost/regex.hpp>
#include <string>
#include <iostream>
int main()
{
std::string s = " Boost Libraries ";
boost::regex expr{"\\s"};
std::string fmt{"_"};
std::cout << boost::regex_replace(s, expr, fmt) << '\n';
}
boost::regex_replace 会替换所有匹配到的字符串,得到 "_Boost_Libraries_."
#include <boost/regex.hpp>
#include <string>
#include <iostream>
int main()
{
std::string s = "Boost Libraries";
boost::regex expr{"(\\w+)\\s(\\w+)"};
std::string fmt{"\\2 \\1"};
std::cout << boost::regex_replace(s, expr, fmt) << '\n';
}
在结果表达式中,可以用数字只带匹配到的结果,得到 "Libraries Boost"
#include <boost/regex.hpp>
#include <string>
#include <iostream>
int main()
{
std::string s = "Boost Libraries";
boost::regex expr{"(\\w+)\\s(\\w+)"};
std::string fmt{"\\2 \\1"};
std::cout << boost::regex_replace(s, expr, fmt,
boost::regex_constants::format_literal) << '\n';
}
也可以用 boost::regex_constants::format_literal 取消这种指代,得到 "\2 \1."
例子:信用卡 💳
参考:https://www.boost.org/doc/libs/1_37_0/libs/regex/doc/html/boost_regex/introduction_and_overview.html
搜索 - regex_match 🔗详情
校验信用卡为例:数字,16位长度,每4位分成一组,以 - 或 _ 连接
(\\d{4}[- ]){3}\\d{4}
bool validate_card_format(const std::string& s)
{
static const boost::regex e("(\\d{4}[- ]){3}\\d{4}");
return regex_match(s, e);
}
替换 - regex_replace 🔗详情
上述信用卡格式是人读的,还有机器格式:数字,15到16位长度,不分组,中间每连接符
于是需要两套识别和转换的代码
const boost::regex e("\\A(\\d{3,4})[- ]?(\\d{4})[- ]?(\\d{4})[- ]?(\\d{4})\\z");
const std::string machine_format("\\1\\2\\3\\4");
const std::string human_format("\\1-\\2-\\3-\\4");
std::string machine_readable_card_number(const std::string s)
{
return regex_replace(s, e, machine_format, boost::match_default | boost::format_sed);
}
std::string human_readable_card_number(const std::string s)
{
return regex_replace(s, e, human_format, boost::match_default | boost::format_sed);
}
CSDN话题挑战赛第2期 参赛话题:学习笔记
|