C++11 (MSVS2012) 正则表达式在多行 std::string 中查找文件名

c++11 (MSVS2012) regex looking for file names in multiple line std::string

本文关键字:std string 文件名 查找 MSVS2012 正则表达式 C++11      更新时间:2023-10-16

我一直在试图寻找一个明确的答案,但找不到它。

所以假设我有一个字符串(其中 可以是 \r - 我想处理两者 - 不确定这是否相关(

"4345t435ng54t a_file_123.xml rkngreg a_file_j34.xml fger 43t54"

然后我想得到匹配:

  • a_file_123.xml
  • a_file_j34.xml

这是我的测试代码:

const str::string s = "4345t435ng54t a_file_123.xml rkngreg a_file_j34.xml fger 43t54";
std::smatch matches;
if (std::regex_search(s, matches, std::regex("a_file_(.*)\.xml")))
{
std::cout << "total: " << matches.size() << std::endl;
for (unsigned int i = 0; i < matches.size(); i++)
{
std::cout << "match: " << matches[i] << std::endl;
}
}

输出为:

total: 2
match: a_file_123.xml
match: 123

我不太明白为什么匹配 2 只是"123"......

您只有一个匹配项,而不是两个,因为regex_search方法返回一个匹配项。您打印的是两个值,组 0(整个匹配项,a_file_123.xml此处(和组 1(捕获组值,此处,123是使用您在模式中定义为(.*)捕获组捕获的子字符串(。

如果要匹配多个字符串,则需要使用正则表达式迭代器,而不仅仅是仅返回第一个匹配项的regex_search

此外,.*太贪婪了,如果在同一行上有超过 1 个匹配项,则会返回奇怪的结果。您似乎要匹配字母或数字,因此.*可以替换为w+.好吧,如果真的有什么,就用.*?.

const std::string s = "4345t435ng54t a_file_123.xml rkngreg a_file_j34.xml fger 43t54";
const std::regex rx("a_file_\w+\.xml");
std::vector<std::string> results(std::sregex_token_iterator(s.begin(), s.end(), rx),
std::sregex_token_iterator());
std::cout << "Number of matches: " << results.size() << std::endl;
for (auto result : results)
{
std::cout << result << std::endl;
}

查看C++演示收益

Number of matches: 2
a_file_123.xml
a_file_j34.xml

关于正则表达式的说明

  • a_file_- 文本子字符串
  • \w+- 1+ 单词字符(字母、数字、_((请注意,如果您想匹配任何字符,您可以在此处使用[^.]*?而不是\w+,0 或更多重复,尽可能少,直到第一个.xml(
  • \.- 一个点(如果你不转义它,它将匹配除换行符之外的任何字符(
  • xml- 文本子字符串。

查看正则表达式演示