修改正则是包括逗号

modify regex to include comma

本文关键字:包括逗 修改      更新时间:2023-10-16

我有以下字符串:

arg1('value1') arg2('value '')2') arg3('user'~!@#$%^&*_~!@#$%^&"*_-=+[{]}|;:<.>?21')

提取值的正则是:

boost::regex re_arg_values("('[^']*(?:''[^']*)*'[^)]*)");

上面的正则拨号正确提取值。但是,当我包括一个逗号时,代码会失败。例如:

  arg1('value1') arg2('value '')2') arg3('user'~!@#$%^&*_~!@#$%^&"*_-=+[{]}|;:<.>?21**,**')

我应该如何修改此正则以包括逗号?供参考。该值可以包含空格,特殊字符以及选项卡。代码在CPP中。

预先感谢。

我在这里不使用正则态度。

目标必须是解析值,毫无疑问它们将具有有用的值,您需要解释。

我会设计一个数据结构:

#include <map>
namespace Config {
    using Key = std::string;
    using Value = boost::variant<int, std::string, bool>;
    using Setting = std::pair<Key, Value>;
    using Settings = std::map<Key, Value>;
}

为此,您可以使用Boost Spirit编写1:1 A解析器:

#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted/std_pair.hpp>
namespace Parser {
    using It = std::string::const_iterator;
    using namespace Config;
    namespace qi = boost::spirit::qi;
    using Skip = qi::blank_type;
    qi::rule<It, std::string()>   quoted_   = "'" >> *(
            "'" >> qi::char_("'") // double ''
          | '' >> qi::char_     // any character escaped
          | ~qi::char_("'")       // non-quotes
       ) >> "'";
    qi::rule<It, Key()>           key_      = +qi::char_("a-zA-Z0-9_"); // for example
    qi::rule<It, Value()>         value_    = qi::int_ | quoted_ | qi::bool_;
    qi::rule<It, Setting(), Skip> setting_  = key_ >> '(' >> value_ >> ')';
    qi::rule<It, Settings()>      settings_ = qi::skip(qi::blank) [*setting_];
}

请注意此

如何
  • 正确解释非弦乐值
  • 指定键的样子,并解析它们
  • 解释字符串Escapes,因此地图中的Value包含"真实"字符串,在Un-Escaping之后
  • 忽略空格外部值(如果您想忽略新线,也可以使用space_type,也可以使用)

您可以像以下方式使用:

int main() {
    std::string const input = R"(    arg1('value1') arg2('value '')2') arg3('user'~!@#$%^&*_~!@#$%^&"*_-=+[{]}|;:<.>?21**,**'))";
    Config::Settings map;
    if (parse(input.begin(), input.end(), Parser::settings_, map)) {
        for(auto& entry : map)
            std::cout << "config setting {" << entry.first << ", " << entry.second << "}n";
    }
}

哪个打印

config setting {arg1, value1}
config setting {arg2, value ')2}
config setting {arg3, user'~!@#$%^&*_~!@#$%^&"*_-=+[{]}|;:<.>?21**,**}

实时演示

活在coliru

#include <boost/spirit/include/qi.hpp>
#include <map>
#include <boost/fusion/adapted/std_pair.hpp>
namespace Config {
    using Key = std::string;
    using Value = boost::variant<int, std::string, bool>;
    using Setting = std::pair<Key, Value>;
    using Settings = std::map<Key, Value>;
}
namespace Parser {
    using It = std::string::const_iterator;
    using namespace Config;
    namespace qi = boost::spirit::qi;
    using Skip = qi::blank_type;
    qi::rule<It, std::string()>   quoted_   = "'" >> *(
            "'" >> qi::char_("'") // double ''
          | '' >> qi::char_     // any character escaped
          | ~qi::char_("'")       // non-quotes
       ) >> "'";
    qi::rule<It, Key()>           key_      = +qi::char_("a-zA-Z0-9_"); // for example
    qi::rule<It, Value()>         value_    = qi::int_ | quoted_ | qi::bool_;
    qi::rule<It, Setting(), Skip> setting_  = key_ >> '(' >> value_ >> ')';
    qi::rule<It, Settings()>      settings_ = qi::skip(qi::blank) [*setting_];
}
int main() {
    std::string const input = R"(    arg1('value1') arg2('value '')2') arg3('user'~!@#$%^&*_~!@#$%^&"*_-=+[{]}|;:<.>?21**,**'))";
    Config::Settings map;
    if (parse(input.begin(), input.end(), Parser::settings_, map)) {
        for(auto& entry : map)
            std::cout << "config setting {" << entry.first << ", " << entry.second << "}n";
    }
}

奖金

为了进行比较,这是"相同",但使用正则:

活在coliru

#include <boost/regex.hpp>
#include <boost/range/iterator_range.hpp>
#include <iostream>
#include <map>
namespace Config {
    using Key = std::string;
    using RawValue = std::string;
    using Settings = std::map<Key, RawValue>;
    Settings parse(std::string const& input) {
        Settings settings;
        boost::regex re(R"((w+)(('.*?')))");
        auto f = boost::make_regex_iterator(input, re);
        for (auto& match : boost::make_iterator_range(f, {}))
            settings.emplace(match[1].str(), match[2].str());
        return settings;
    }
}
int main() {
    std::string const input = R"(    arg1('value1') arg2('value '')2') arg3('user'~!@#$%^&*_~!@#$%^&"*_-=+[{]}|;:<.>?21**,**'))";
    Config::Settings map = Config::parse(input);
    for(auto& entry : map)
        std::cout << "config setting {" << entry.first << ", " << entry.second << "}n";
}

打印

config setting {arg1, 'value1'}
config setting {arg2, 'value ''}
config setting {arg3, 'user'~!@#$%^&*_~!@#$%^&"*_-=+[{]}|;:<.>?21**,**'}

注意:

  • 它不再解释并转换任何值
  • 它不再处理逃逸
  • 它需要对BOOST_REGEX的额外运行时库