gpt4 book ai didi

c++ - 正则表达式:查找所有子表达式(使用 boost::regex)

转载 作者:搜寻专家 更新时间:2023-10-31 02:22:02 25 4
gpt4 key购买 nike

我有一个文件,其中包含一些 Valve 格式的“实体”数据。它基本上是一个键值交易,看起来像这样:

{
"world_maxs" "3432 4096 822"
"world_mins" "-2408 -4096 -571"
"skyname" "sky_alpinestorm_01"
"maxpropscreenwidth" "-1"
"detailvbsp" "detail_sawmill.vbsp"
"detailmaterial" "detail/detailsprites_sawmill"
"classname" "worldspawn"
"mapversion" "1371"
"hammerid" "1"
}
{
"origin" "553 -441 322"
"targetname" "tonemap_global"
"classname" "env_tonemap_controller"
"hammerid" "90580"
}

每对 {}算作一个实体,里面的行算作键值。如您所见,它非常简单。

我想将这些数据处理成 vector<map<string, string> >在 C++ 中。为此,我尝试使用 Boost 附带的正则表达式。这是我目前所拥有的:

static const boost::regex entityRegex("\\{(\\s*\"([A-Za-z0-9_]+)\"\\s*\"([^\"]+)\")+\\s*\\}");
boost::smatch what;
while (regex_search(entitiesString, what, entityRegex)) {
cout << what[0] << endl;
cout << what[1] << endl;
cout << what[2] << endl;
cout << what[3] << endl;
break; // TODO
}

更易于阅读的正则表达式:

\{(\s*"([A-Za-z0-9_]+)"\s*"([^"]+)")+\s*\}

我不确定正则表达式是否适合我的问题,但它似乎至少打印了最后一个键值对 (hammerid, 1)。

我的问题是,我将如何在表达式中提取“第 n 个”匹配的子表达式?或者真的没有一个实用的方法来做到这一点?写两个嵌套的 while 会更好吗? -loops,一个搜索 {} 的循环模式,然后是搜索实际键值对的模式?

谢谢!

最佳答案

使用解析器生成器,您可以编写适当的解析器。

例如,使用 Boost Spirit,您可以将内联语法规则定义为 C++ 表达式:

    start  = *entity;
entity = '{' >> *entry >> '}';
entry = text >> text;
text = '"' >> *~char_('"') >> '"';

这是一个完整的演示:

Live On Coliru

#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted/std_pair.hpp>
#include <map>

using Entity = std::map<std::string, std::string>;
using ValveData = std::vector<Entity>;

namespace qi = boost::spirit::qi;

template <typename It, typename Skipper = qi::space_type>
struct Grammar : qi::grammar<It, ValveData(), Skipper>
{
Grammar() : Grammar::base_type(start) {
using namespace qi;

start = *entity;
entity = '{' >> *entry >> '}';
entry = text >> text;
text = '"' >> *~char_('"') >> '"';

BOOST_SPIRIT_DEBUG_NODES((start)(entity)(entry)(text))
}
private:
qi::rule<It, ValveData(), Skipper> start;
qi::rule<It, Entity(), Skipper> entity;
qi::rule<It, std::pair<std::string, std::string>(), Skipper> entry;
qi::rule<It, std::string()> text;
};

int main()
{
using It = boost::spirit::istream_iterator;
Grammar<It> parser;
It f(std::cin >> std::noskipws), l;

ValveData data;
bool ok = qi::phrase_parse(f, l, parser, qi::space, data);

if (ok) {
std::cout << "Parsing success:\n";

int count = 0;
for(auto& entity : data)
{
++count;
for (auto& entry : entity)
std::cout << "Entity " << count << ": [" << entry.first << "] -> [" << entry.second << "]\n";
}
} else {
std::cout << "Parsing failed\n";
}

if (f!=l)
std::cout << "Remaining unparsed input: '" << std::string(f,l) << "'\n";
}

打印(对于显示的输入):

Parsing success:
Entity 1: [classname] -> [worldspawn]
Entity 1: [detailmaterial] -> [detail/detailsprites_sawmill]
Entity 1: [detailvbsp] -> [detail_sawmill.vbsp]
Entity 1: [hammerid] -> [1]
Entity 1: [mapversion] -> [1371]
Entity 1: [maxpropscreenwidth] -> [-1]
Entity 1: [skyname] -> [sky_alpinestorm_01]
Entity 1: [world_maxs] -> [3432 4096 822]
Entity 1: [world_mins] -> [-2408 -4096 -571]
Entity 2: [classname] -> [env_tonemap_controller]
Entity 2: [hammerid] -> [90580]
Entity 2: [origin] -> [553 -441 322]
Entity 2: [targetname] -> [tonemap_global]

关于c++ - 正则表达式:查找所有子表达式(使用 boost::regex),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30781743/

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