正则表达式
正则表达式(Regular Expression,简称 regex)是一种用于匹配字符串的模式。它由一系列字符和特殊符号组成,用于描述、匹配一系列符合某个句法规则的字符串。正则表达式广泛应用于文本搜索、替换、验证等场景。
它的主要功能包括:模式匹配,可以识别特定格式的字符串,例如电子邮件地址、电话号码等;字符串搜索,在大量文本中快速找到符合特定模式的内容;文本替换,可以根据匹配的模式,对字符串进行替换操作;验证输入,检查用户输入是否符合预定格式(如密码复杂度、日期格式等),等等。
主要应用方面包括:数据清洗,在数据处理和分析中,去除无效或不必要的文本;Web开发,验证表单输入、解析URL等;文本编辑器,搜索和替换功能;编程语言,在代码中处理字符串的复杂需求,等等。
总的来说,正则表达式是一种文本模式,该模式描述在搜索文本时要匹配的一个或多个字符串。
组成符号
正则表达式由一些普通字符和一些元字符(metacharacters)组成。普通字符包括大小写的字母和数字,而元字符则具有特殊的含义,我们下面会给予解释。
在最简单的情况下,一个正则表达式看上去就是一个普通的查找串。例如,正则表达式"testing"中没有包含任何元字符,它可以匹配"testing"和"testing123"等字符串,但是不能匹配"Testing"。
要想真正的用好正则表达式,正确的理解元字符是最重要的事情。下表列出了所有的元字符和对它们的一个简短的描述。
regex_match
regex_match
是 C++ 标准库 <regex>
中的一个函数,用于从字符串中提取匹配的子串。这种形式允许将匹配的结果存储在 std::smatch
对象中,以便进一步处理。
bool regex_match(
const std::string& src, // 原始字符串
std::smatch& matches, // 存储匹配结果的容器
const std::regex& e // 正则表达式
);
参数说明
const std::string& src:要匹配的原始字符串。 std::smatch& matches:用于存储匹配结果的容器。std::smatch 是 std::match_results 的一个特化版本,专门用于 std::string。
它类似于一个数组,可以通过索引访问匹配的子串:
-
matches[0]:整个匹配的字符串。
-
matches[1]:第一个捕获组(即第一个括号内的内容)。
-
matches[2]:第二个捕获组,以此类推。
const std::regex& e:类型为 const std::regex&,是一个已经编译好的正则表达式对象。std::regex 用于表示一个正则表达式模式,通过它可以对输入字符串进行匹配操作。
返回值
如果整个字符串 src 完全匹配正则表达式 e,返回 true。否则,返回 false。
使用示例
#include <iostream>
#include <regex>
#include <string>
int main() {
std::string src = "hello123";
std::regex e("(hello)(\\d+)");
std::smatch matches;
if (std::regex_match(src, matches, e)) {
std::cout << "整个匹配的字符串: " << matches[0] << std::endl;
std::cout << "第一个捕获组: " << matches[1] << std::endl;
std::cout << "第二个捕获组: " << matches[2] << std::endl;
} else {
std::cout << "字符串不匹配正则表达式" << std::endl;
}
return 0;
}
在这个示例中,我们尝试将字符串 "hello123"
与正则表达式 "(hello)(\\d+)"
进行匹配。正则表达式中的 (hello)
是第一个捕获组,(\\d+)
是第二个捕获组,用于匹配一个或多个数字。如果匹配成功,会输出整个匹配的字符串以及各个捕获组的内容;如果匹配失败,则会输出相应的提示信息。
需要注意的是,std::regex_match
要求整个输入字符串都要与正则表达式完全匹配,如果只想查找字符串中是否包含符合正则表达式的子串,应该使用 std::regex_search
函数。
正则表达式的使用,可以使得HTTP请求的解析更加简单(这里指的时程序员的工作变得的简单,这并不代表处理效率会变高,实际上效率上是低于直接的字符串处理的),使我们实现的HTTP组件库使用起来更加灵活。
#include <iostream>
#include <string>
#include <regex>
int main()
{
// HTTP 请求行格式 GET /index.html HTTP/1.1\r\n 请求方法+资源路径(+查询字符串)+HTTP版本
std::string str = "GET /wuxu/login?user=xiaoming&pass=123123 HTTP/1.1\r\n";
// std::string str = "GET /wuxu/login HTTP/1.1\r\n";
std::smatch matches;
// 请求方法的匹配 GET HEAD POST PUT DELETE ...
std::regex e("(GET|HEAD|POST|PUT|DELETE) ([^?]*)(?:\\?(.*))? (HTTP/1\\.[01])(?:\n|\r\n)?");
/*
GET|HEAD|POST|PUT|DELETE 表示匹配并提取其中任意一个字符串
[^?]* [^?]匹配非问号字符,后边的*表示0次或多次
\\?(.*) \\? 表示原始的?字符(.*)表示提取?之后的任意字符0次或多次,直到遇到空格
HTTP/1\\.[01] 表示匹配HTTP/1.开始,后边有个0或1的字符串
(?:\n|\r\n)? (?: ...)表示匹配某个格式字符串,但是不提取 最后的?表示的是匹配前边的表达式0次或1次
*/
bool ret = std::regex_match(str, matches, e);
if(ret == false) return -1;
for(auto& s : matches)
std::cout << s << std::endl;
return 0;
}