C++使用正则表达式解析.srt字幕文件
SRT文件
.srt是一种非常流行的基于文本行格式的字幕文件。一个简单的字幕文件的内容如下(本文不考虑字幕有多行的情况):
1 | 1 |
其内容包括序号,开始时间和结束时间,以及字幕的文本内容,以\r\n相互隔开,最后以\r\n\r\n结束,这样的格式很容易通过正则表达式匹配来解析。
使用C#的正则表达式匹配
在C#中使用.net的正则表达式匹配,示例如下:
1 | //data为已经从srt文件中读取的文本 |
输出如下:
1 | 序号: 1 开始时间: 00:00:53,477 结束时间: 00:00:54,845 文本: 大唐 |
使用C++的正则表达式匹配
与.net的正则表达式不同,C++的STL中的正则表达式并没有提供类似Regex.Matchs这种可以匹配多个结果的支持。
- std::regex_match用于完全匹配一个字符串。
- std::regex_search用于搜索字符序列中是否存在匹配的一个子串。
- std::regex_replace用于替换。
但是这并不意味着就没办法用C++的正则表达式来解析了,只是相对.net会稍显麻烦一些。
- 方法一 使用std::regex_search每次匹配一个结果,下一次从当前匹配的结尾处开始继续往后匹配,如此重复直到匹配失败。输出如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27//data为已经从srt文件中读取的文本
std::string data = "1\r\n00:00:53,477 --> 00:00:54,845\r\n大唐\r\n\r\n2\r\n00:00:55,212 --> 00:00:57,280\r\n我夙夜忧思的母国\r\n\r\n3\r\n00:00:58,615 --> 00:00:59,750\r\n洛阳\r\n\r\n4\r\n00:01:00,250 --> 00:01:02,419\r\n我魂萦梦系之地\r\n\r\n5\r\n00:01:05,389 --> 00:01:06,890\r\n三十岁那年\r\n\r\n";
//如果编译器不支持C++11的raw string literals 下面一句可以写成 std::regex regex("(\\d+)\\r\\n(\\d+:\\d{2}:\\d{2},\\d{3})\\s-->\\s(\\d+:\\d{2}:\\d{2},\\d{3})\\r\\n(.*)\\r\\n\\r\\n");
std::regex regex(R"((\d+)\r\n(\d+:\d{2}:\d{2},\d{3})\s-->\s(\d+:\d{2}:\d{2},\d{3})\r\n(.*)\r\n\r\n)");
std::match_results<std::string::const_iterator> match_results;
auto begin = data.cbegin();
std::vector<std::tuple<std::string, std::string, std::string, std::string>> vec;
while (begin != data.cend())
{
if (std::regex_search(begin, data.cend(), match_results, regex))
{
vec.emplace_back(match_results[1], match_results[2], match_results[3], match_results[4]);
begin = match_results.suffix().first;
}
else
{
break;
}
}
for (const auto& t : vec)
{
std::cout << "序号: " << std::get<0>(t)
<< " 开始时间: " << std::get<1>(t)
<< " 结束时间: " << std::get<2>(t)
<< " 文本: " << std::get<3>(t)
<< std::endl;
}1
2
3
4
5序号: 1 开始时间: 00:00:53,477 结束时间: 00:00:54,845 文本: 大唐
序号: 2 开始时间: 00:00:55,212 结束时间: 00:00:57,280 文本: 我夙夜忧思的母国
序号: 3 开始时间: 00:00:58,615 结束时间: 00:00:59,750 文本: 洛阳
序号: 4 开始时间: 00:01:00,250 结束时间: 00:01:02,419 文本: 我魂萦梦系之地
序号: 5 开始时间: 00:01:05,389 结束时间: 00:01:06,890 文本: 三十岁那年 - 方法二 博主暂时没想到比方法一更简便有效的方法。