c++ - 标记化字符串,接受 CPP 中给定字符集之间的所有内容

标签 c++ regex boost

我有以下代码:

   int main()
{
  string s = "server ('m1.labs.teradata.com') username ('use\\')r_*5') password('u\" er 5') dbname ('default')";

    regex re("(\'[!-~]+\')");
    sregex_token_iterator i(s.begin(), s.end(), re, 1);
    sregex_token_iterator j;

    unsigned count = 0;
    while(i != j)
    {
        cout << "the token is  "<<*i<< endl;
        count++;
    }
    cout << "There were " << count << " tokens found." << endl;

  return 0;
}

使用上面的正则表达式,我想提取括号和单引号之间的字符串:,输出应该如下所示:

the token is   'm1.labs.teradata.com'
the token is   'use\')r_*5'
the token is   'u" er 5'
the token is   'default'
There were 4 tokens found.

基本上,正则表达式应该提取“('”和“')”之间的所有内容。它可以是任何空格、特殊字符、引号或结束句。 我之前使用过以下正则表达式:

boost::regex re_arg_values("(\'[!-~]+\')");

但是它不接受空间。请有人帮我解决这个问题。提前致谢。

最佳答案

这是使用 Spirit X3 创建语法以实际解析它的示例。我想解析成(键->值)对的映射,这比盲目地假设名称总是相同更有意义:

using Config = std::map<std::string, std::string>;
using Entry  = std::pair<std::string, std::string>;

现在,我们使用 X3 设置一些语法规则:

namespace parser {
    using namespace boost::spirit::x3;

    auto value  = quoted("'") | quoted('"');
    auto key    = lexeme[+alpha];
    auto pair   = key >> '(' >> value >> ')';
    auto config = skip(space) [ *as<Entry>(pair) ];
}

helper as<>quoted是简单的 lambda:

template <typename T> auto as = [](auto p) { return rule<struct _, T> {} = p; };
auto quoted = [](auto q) { return lexeme[q >> *('\\' >> char_ | char_ - q) >> q]; };

现在我们可以直接将字符串解析成一个映射:

Config parse_config(std::string const& cfg) {
    Config parsed;
    auto f = cfg.begin(), l = cfg.end();
    if (!parse(f, l, parser::config, parsed))
        throw std::invalid_argument("Parse failed at " + std::string(f,l));
    return parsed;
}

和演示程序

int main() {
    Config cfg = parse_config("server ('m1.labs.teradata.com') username ('use\\')r_*5') password('u\" er 5') dbname ('default')");

    for (auto& setting : cfg)
        std::cout << "Key " << setting.first << " has value " << setting.second << "\n";
}

打印

Key dbname has value default
Key password has value u" er 5
Key server has value m1.labs.teradata.com
Key username has value use')r_*5

现场演示

Live On Coliru

#include <iostream>
#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/adapted/std_pair.hpp>
#include <map>

using Config = std::map<std::string, std::string>;
using Entry  = std::pair<std::string, std::string>;

namespace parser {
    using namespace boost::spirit::x3;

    template <typename T> auto as = [](auto p) { return rule<struct _, T> {} = p; };
    auto quoted = [](auto q) { return lexeme[q >> *(('\\' >> char_) | (char_ - q)) >> q]; };

    auto value  = quoted("'") | quoted('"');
    auto key    = lexeme[+alpha];
    auto pair   = key >> '(' >> value >> ')';
    auto config = skip(space) [ *as<Entry>(pair) ];
}

Config parse_config(std::string const& cfg) {
    Config parsed;
    auto f = cfg.begin(), l = cfg.end();
    if (!parse(f, l, parser::config, parsed))
        throw std::invalid_argument("Parse failed at " + std::string(f,l));
    return parsed;
}

int main() {
    Config cfg = parse_config("server ('m1.labs.teradata.com') username ('use\\')r_*5') password('u\" er 5') dbname ('default')");

    for (auto& setting : cfg)
        std::cout << "Key " << setting.first << " has value " << setting.second << "\n";
}

奖金

如果你想学习如何提取原始输入:试试

auto source = skip(space) [ *raw [ pair ] ]; 

像这样:

using RawSettings = std::vector<std::string>;

RawSettings parse_raw_config(std::string const& cfg) {
    RawSettings parsed;
    auto f = cfg.begin(), l = cfg.end();
    if (!parse(f, l, parser::source, parsed))
        throw std::invalid_argument("Parse failed at " + std::string(f,l));
    return parsed;
}

int main() {
    for (auto& setting : parse_raw_config(text))
        std::cout << "Raw: " << setting << "\n";
}

打印: Live On Coliru

Raw: server ('m1.labs.teradata.com')
Raw: username ('use\')r_*5')
Raw: password('u" er 5')
Raw: dbname ('default')

关于c++ - 标记化字符串,接受 CPP 中给定字符集之间的所有内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45237637/

相关文章:

c++ - 在 linux ubuntu 服务器 11.10 (vps) 上使用 asio 使用 C++ 进行编译

c++ - 可以搜索相同成本的值和键的 map ?对称 map ?

c++ - 带有写时复制分支的 std::forward

android - 如何在 Qt Android 应用程序上禁用屏幕保护程序

c# - 解析 .NET 中类似内容的简单正则表达式问题?

.net - 根据 Regex.Matches MatchCollection 替换字符串中的内容

c++ - 在 mac os x 上安装 boost 和 PyUblas 时出错

c++ - OpenCV:arcLength 断言因 cv::Mat 而失败

c++ - 递归函数错误

Javascript 使用正则表达式匹配组替换 HTML 标签