gpt4 book ai didi

c++ - 使用 std::regex 过滤输入

转载 作者:太空狗 更新时间:2023-10-29 20:36:21 26 4
gpt4 key购买 nike

我有一个乱七八糟的字符串,它由几个 URI 组成。

:/SymbolStandards/JMSymbology/MIL_STD_2525D_Symbols/0_301_0.svg,:/SymbolStandards/JMSymbology/MIL_STD_2525D_Symbols/02011.svg,:/SymbolStandards/JMSymbology/MIL_STD_2525D_Symbols/02012.svg,:/SymbolStandards/JMSymbology/MIL_STD_2525D_Symbols/02110000.svg

我想做的是去掉字符 :/., 的每一次出现,这样我就可以得到一个可以作为有效文件名的字符串。

为了做到这一点,我写了这个简单的正则表达式:[^(:/,.)]根据 http://www.regexpal.com/,这似乎是正确的正则表达式.

但是,当我运行以下 C++ 代码时,我没有得到我期望的结果(只有字母数字字符和下划线),我只得到序列中的第一个字母数字字符:S .

我对 std::regex 做错了什么,或者我的正则表达式关闭了吗?

#include <iostream>
#include <regex>
#include <string>

static const std::string filenames {R"(:/SymbolStandards/JMSymbology/MIL_STD_2525D_Symbols/0_301_0.svg,:/SymbolStandards/JMSymbology/MIL_STD_2525D_Symbols/02011.svg,:/SymbolStandards/JMSymbology/MIL_STD_2525D_Symbols/02012.svg,:/SymbolStandards/JMSymbology/MIL_STD_2525D_Symbols/02110000.svg)"};
static const std::regex filename_extractor("[^(:/,.)]");

int main() {
std::smatch filename_match;
if(std::regex_search(filenames, filename_match, filename_extractor))
{
std::cout << "Number of filenames: " << filename_match.size() << std::endl;
for(std::size_t i = 0; i < filename_match.size(); ++i)
{
std::cout << i << ": " << filename_match[i] << std::endl;
}
}

return 0;
}

最佳答案

size()std::smatch返回子表达式的数量 + 1(带有 () ,您没有)。

解决方案

您需要调用 std::regex_search 重复,或使用 std::regex_iterator .

此外,您的正则表达式实际上只搜索了一个字符。您需要使用 +搜索最长的字符序列:[^(:/,.)]+ .

这是您的代码,结合了 cppreference.com 中的示例:

#include <iostream>
#include <iterator>
#include <regex>
#include <string>

static const std::string filenames {R"(:/SymbolStandards/JMSymbology/MIL_STD_2525D_Symbols/0_301_0.svg,:/SymbolStandards/JMSymbology/MIL_STD_2525D_Symbols/02011.svg,:/SymbolStandards/JMSymbology/MIL_STD_2525D_Symbols/02012.svg,:/SymbolStandards/JMSymbology/MIL_STD_2525D_Symbols/02110000.svg)"};
static const std::regex filename_extractor("[^(:/,.)]+");

int main() {
auto files_begin = std::sregex_iterator(filenames.begin(), filenames.end(), filename_extractor);

for (auto i = files_begin; i != std::sregex_iterator(); ++i) {
std::string filename = i->str();
std::cout << filename << '\n';
}

return 0;
}

但是,这也会返回中间“目录”。如果您使用正则表达式 [^(:,)]+ ,你会得到希望你想要的结果:

/SymbolStandards/JMSymbology/MIL_STD_2525D_Symbols/0_301_0.svg
/SymbolStandards/JMSymbology/MIL_STD_2525D_Symbols/02011.svg
/SymbolStandards/JMSymbology/MIL_STD_2525D_Symbols/02012.svg
/SymbolStandards/JMSymbology/MIL_STD_2525D_Symbols/02110000.svg

您的问题已解释

std::regex_search仅搜索 第一次 出现的正则表达式,以及其中的任何子表达式。

例如,表达式 ab([cd])([ef])将匹配字符串 xxabcfxxabdef .第一个匹配项是 abcf 部分, 与 c匹配第一个子表达式 [cd]e作为第二个子表达式的匹配 [ef] .

第二个匹配是abde的部分(不是 abdef !),其中 e是第二个子表达式的匹配项。

std::regex_search ,您搜索第一个匹配项,匹配器返回完整的 第一个 匹配项和子表达式的匹配项。如果要查找更多匹配项,则必须从字符串的其余部分 ( std::smatch::suffix()) 开始搜索。

此外,正则表达式 [ef]只匹配一个字符。 [ef]+将匹配 e 的最长序列s 和 f秒。因此,匹配 ab([cd])([ef]) 的第二个子表达式对于上面的目标字符串将匹配 ef , 而不仅仅是 e .

关于c++ - 使用 std::regex 过滤输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38923448/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com