gpt4 book ai didi

c++ - 如何使用 std::regex_search 查找所有出现的模式?

转载 作者:行者123 更新时间:2023-11-30 05:38:16 32 4
gpt4 key购买 nike

我有以下代码可以从任意格式的文件中解析一堆零件号(基本上是产品组件的序列号)。

auto buildPartNumberRegexString( bool preFlash ) -> std::string
{
std::ostringstream patternBuilder;

// The original, raw literal as tested on https://regex101.com/ is:
//
// @@PART_NUMBER_POST_FLASH\<\s*(\S+)\s*\,\s*(\d+)\s*\>@@
//
// In C++, each backslash needs to be doubled. Alternatively, we could use raw string literals ( R"\w" ).

patternBuilder << "@@PART_NUMBER_" << ( preFlash ? "PRE" : "POST" )
<< "_FLASH\\<\\s*(\\S+)\\s*\\,\\s*(\\d+)\\s*\\>@@";

return patternBuilder.str();
}

auto parsePartNumberAddresses( const std::string& templateFileContent, bool preFlash ) -> ParamAddressContainer
{
const std::regex regEx( buildPartNumberRegexString( preFlash ) );
std::smatch match;

if ( std::regex_search( templateFileContent, match, regEx ) )
{
assert( match.size() > 1 );
const std::size_t capturedGroups = match.size() - 1;

assert( capturedGroups % 2 == 0 );
const std::size_t partNumberAddressesFound = capturedGroups / 2;

ParamAddressContainer results;
results.reserve( partNumberAddressesFound );

std::cerr << "DEBUG: capturedGroups = " << capturedGroups << ", partNumberAddressesFound = " << partNumberAddressesFound
<< "\n";

for ( std::size_t i = 0; i < partNumberAddressesFound; ++i )
{
const std::size_t paramIdMatchIndex = i * 2 + 1;
const std::string paramIdString = match.str( paramIdMatchIndex );
const std::string paramIndexString = match.str( paramIdMatchIndex + 1 );

results.emplace_back( util::string_funcs::fromString< ParamId_t > ( paramIdString ),
util::string_funcs::fromString< ParamIndex_t > ( paramIndexString ) );
}

std::cerr << "DEBUG: Going to read the following part numbers (" << ( preFlash ? "pre" : "post" ) << "-flash):\n\n";

for ( const auto& paramAddress : results )
{
std::cerr << "\t" << std::hex << std::noshowbase << paramAddress.paramId << std::dec << "<" << paramAddress.paramIndex
<< ">\n";
}

return results;
}

return ParamAddressContainer();
}

我在 buildPartNumberRegexString 函数的注释中编写了“美化”正则表达式(即没有转义实际反斜杠所需的双反斜杠)。

我正在使用此正则表达式的示例文件可能如下所示:

Component alpha;@@PART_NUMBER_POST_FLASH<F12C,0>@@
Component beta;@@PART_NUMBER_POST_FLASH<F12C,1>@@

我已经在 https://regex101.com/ 上使用相同的示例文件测试了我的正则表达式它完全按照它应该的方式工作,匹配两次出现并提取所需的匹配组。问题是,当我尝试通过 std::regex 做同样的事情时,它只会找到第一个匹配项。现在 https://regex101.com/我必须为正则表达式启用 g 修饰符 (全局,所有匹配项,不返回第一个匹配项) 以查找所有匹配项。我假设(希望)类似的标志可用于 std::regex_search,但可用标志的描述 (http://en.cppreference.com/w/cpp/regex/match_flag_type) 似乎没有列出任何符合我要求的标志。当然必须有一种方法可以找到不止一次出现的模式,对吧?有人有想法吗?

最佳答案

很抱歉,如果人们觉得这不值得发布我自己的问题的答案,但我想我会为其他也在寻找解决方案的人发布我的更新和工作解决方案。好的,按照 Cubbi 的建议,我决定使用 std::regex_iterator,我更喜欢它而不是必须重复调用 std::regex_search。下面是我修改后的 parsePartNumberAddresses 函数:

auto parsePartNumberAddresses( const std::string& templateFileContent, bool preFlash ) -> ParamAddressContainer
{
const std::regex regEx( buildPartNumberRegexString( preFlash ) );

const auto begin_iterator = std::sregex_iterator( templateFileContent.cbegin(), templateFileContent.cend(), regEx );
const auto end_iterator = std::sregex_iterator();

ParamAddressContainer results;

for ( std::sregex_iterator it = begin_iterator; it != end_iterator; ++it )
{
const std::smatch& match = *it;
assert( match.size() == 3 );

const std::string paramIdString = match.str( 1 );
const std::string paramIndexString = match.str( 2 );

results.emplace_back( util::string_funcs::fromString< ParamId_t > ( paramIdString ),
util::string_funcs::fromString< ParamIndex_t > ( paramIndexString ) );
}

std::cerr << "DEBUG: Going to read the following part numbers (" << ( preFlash ? "pre" : "post" ) << "-flash):\n\n";

for ( const auto& paramAddress : results )
{
std::cerr << "\t" << std::hex << std::noshowbase << paramAddress.paramId << std::dec << "<" << paramAddress.paramIndex
<< ">\n";
}

return results;
}

这完全符合预期,在主题字符串中给出了所有 匹配项。 :)

更新:根据 rici 的建议,删除了多余的 std::distance() 以及 results.reserve() 调用以防止对正则表达式求值两次。

关于c++ - 如何使用 std::regex_search 查找所有出现的模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32845267/

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