正则表达式的概念和语法
用于描述和匹配字符串的工具,通过特定的语法规则,灵活的定义复杂字符串匹配条件
常用语法总结
基本字符匹配
a
:匹配字符'a'abc
:匹配字符串'abc'元字符(特殊含义的字符)
.
:匹配任意单个字符(除了换行符)^
:匹配字符串的开始位置$
:匹配字符串的结束位置*
:匹配前面的元素零次或多次+
:匹配前面的元素一次或多次?
:匹配前面的元素零次或一次|
:表示逻辑“或”操作\
:转义字符,用于匹配特殊字符字符类(匹配一组字符中的任意一个)
[abc]
:匹配'a'、'b'或'c'[a-z]
:匹配所有小写字母[^abc]
:匹配除'a'、'b'、'c'之外的任意字符预定义字符类
\d
:匹配任何数字,等价于[0-9]
\D
:匹配任何非数字字符\w
:匹配任何字母、数字或下划线,等价于[a-zA-Z0-9_]
\W
:匹配任何非字母、数字或下划线字符\s
:匹配任何空白字符(空格、制表符等)\S
:匹配任何非空白字符重复限定符
{n}
:匹配前面的元素恰好n次{n,}
:匹配前面的元素至少n次{n,m}
:匹配前面的元素至少n次,至多m次分组与捕获(分组和捕获匹配的字符串)
(abc)
:匹配'abc',并捕获该匹配(?:abc)
:匹配'abc',但不捕获该匹配断言(匹配位置)
(?=...)
:正向先行断言,要求后面的字符必须匹配(?!...)
:负向先行断言,要求后面的字符不能匹配(?<=...)
:正向后行断言,要求前面的字符必须匹配(?<!...)
:负向后行断言,要求前面的字符不能匹配
使用
创建正则表达式对象
正则匹配(检查是否一致);正则搜索(只要包含即可)
正则替换:通过正则表达式,对字符串中的字符进行更换
提取匹配的子字符串,提取的子字符串都存储在了smatch中
处理异常:使用try_catch捕获异常
测试代码汇总
#include <iostream>
#include <regex>
#include <string>
int main()
{
// std::regex pattern("abc");
//正则匹配
// std::string str = "abcddfd";
// if(std::regex_match(str,pattern))
// {
// std::cout<<"match fount"<<std::endl;
// }
// else
// {
// std::cout<<"match not found"<<std::endl;
// }
// //正则搜索(只要有查询的字符即可)
// if(std::regex_search(str,pattern))
// {
// std::cout<<"search found"<<std::endl;
// }
// else
// {
// std::cout<<"search not fount"<<std::endl;
// }
// //正则替换
// std::string replaced = std::regex_replace(str,pattern,"mmm");
// std::cout<<replaced<<std::endl;
//提取匹配的子字符串
std::string str1 = "abc123";
std::regex pattern("(abc)(\\d+)");
std::smatch matches;
if(std::regex_search(str1,matches,pattern))
{
for(size_t i =0;i<matches.size();i++)
{
std::cout << "Match " << i << ": " << matches[i].str() << std::endl;
}
}
return 0;
}
HTTP解析和响应
解析请求分析
([A-Z]+)
:
[A-Z]
:匹配单个大写字母。+
:匹配前面的字符一次或多次,即匹配一个或多个大写字母。()
:捕获组,用于提取匹配的子字符串。- 这个部分匹配HTTP方法,如
GET
、POST
、PUT
等。
(.+)
:
.
:匹配任意单个字符(除换行符外)。+
:匹配前面的字符一次或多次,即匹配一个或多个任意字符。()
:捕获组,用于提取匹配的子字符串。- 这个部分匹配请求的路径,如
/index.html
。
HTTP/([0-9\\.]+)
:
HTTP/
:匹配字符串HTTP/
。[0-9\\.]
:匹配数字(0-9
)或点号(.
)。+
:匹配前面的字符一次或多次,即匹配一个或多个数字或点号。()
:捕获组,用于提取匹配的子字符串。- 这个部分匹配HTTP版本号,如
1.1
。
\r\n
:
\r
:匹配回车符。\n
:匹配换行符。- 这个部分匹配HTTP请求行的结尾。
解析头部字段
([A-Za-z-]+)
:
[A-Za-z-]
:匹配单个字母(大小写皆可)或连字符。+
:匹配前面的字符一次或多次,即匹配一个或多个字母或连字符。()
:捕获组,用于提取匹配的子字符串。- 这个部分匹配头部字段的名称,如
Host
、User-Agent
、Accept
等:
- 匹配冒号和一个空格,作为头部字段名称与值的分隔符。
(.+)
.
:匹配任意单个字符(除换行符外)。+
:匹配前面的字符一次或多次,即匹配一个或多个任意字符。()
:捕获组,用于提取匹配的子字符串。- 这个部分匹配头部字段的值,如
www.example.com
、curl/7.68.0
、*/*
等。/r/n
\r
:匹配回车符。\n
:匹配换行符。- 这个部分匹配头部字段行的结尾
构成响应
- 构建状态行:HTTP版本+状态码+状态描述符
- 构建头部字段:遍历headers哈希表,将其加入到响应字符串职工
- 构建响应体:头部字段后添加一个空行\r\n,然后追加响应体内容
完整测试代码
#include <iostream>
#include <regex>
#include <string>
#include <map>
struct HttpRequest {
std::string method;
std::string path;
std::string version;
std::map<std::string, std::string> headers;
std::string body;
};
HttpRequest parseHttpRequest(const std::string& request) {
HttpRequest httpRequest;
std::regex requestLinePattern("([A-Z]+) (.+) HTTP/([0-9\\.]+)\r\n");
std::regex headerPattern("([A-Za-z-]+): (.+)\r\n");
std::smatch matches;
// 解析请求行
if (std::regex_search(request, matches, requestLinePattern)) {
httpRequest.method = matches[1].str();
httpRequest.path = matches[2].str();
httpRequest.version = matches[3].str();
}
// 解析头部字段
auto headersBegin = std::sregex_iterator(request.begin(), request.end(), headerPattern);
auto headersEnd = std::sregex_iterator();
for (std::sregex_iterator i = headersBegin; i != headersEnd; ++i) {
std::smatch match = *i;
httpRequest.headers[match[1].str()] = match[2].str();
}
// 查找请求体的开始位置
size_t bodyPos = request.find("\r\n\r\n");
if (bodyPos != std::string::npos) {
httpRequest.body = request.substr(bodyPos + 4);
}
return httpRequest;
}
std::string generateHttpResponse(const std::string& status, const std::map<std::string, std::string>& headers, const std::string& body) {
std::string response = "HTTP/1.1 " + status + "\r\n";
for (const auto& header : headers) {
response += header.first + ": " + header.second + "\r\n";
}
response += "\r\n" + body;
return response;
}
int main() {
std::string request = "GET /index.html HTTP/1.1\r\nHost: www.example.com\r\nUser-Agent: curl/7.68.0\r\nAccept: */*\r\n\r\n";
// 解析HTTP请求
HttpRequest httpRequest = parseHttpRequest(request);
// 打印解析结果
std::cout << "Method: " << httpRequest.method << std::endl;
std::cout << "Path: " << httpRequest.path << std::endl;
std::cout << "Version: " << httpRequest.version << std::endl;
for (const auto& header : httpRequest.headers) {
std::cout << header.first << ": " << header.second << std::endl;
}
std::cout << "Body: " << httpRequest.body << std::endl;
// 生成HTTP响应
std::map<std::string, std::string> headers = {
{"Content-Type", "text/html"},
{"Content-Length", "13"}
};
std::string body = "<h1>Hello</h1>";
std::string response = generateHttpResponse("200 OK", headers, body);
// 打印响应报文
std::cout << response << std::endl;
return 0;
}