【问题标题】:Extract everything apart from what is specified in the regex提取除正则表达式中指定的内容之外的所有内容
【发布时间】:2017-12-29 16:33:30
【问题描述】:

我有以下代码:

#include <iostream>
#include <regex>

using namespace std;

int main()
{
    string s;

    s = "server ('m1.labs.terad  ''ata.com') username ('us\* er5') password('user)5') dbname ('def\\ault')";

    regex re("('[^']*(?:''[^']*)*')");
    // I have used -1 to extract everything apart from the content there in brackets.
    sregex_token_iterator i(s.begin(), s.end(), re, -1);
    sregex_token_iterator j;

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

    return 0;
}

上面的正则表达式用于提取参数名称,例如服务器、用户名、密码等。

但这是我得到的输出:

server (
) username (
) password(
) dbname (
)
There were 5 tokens found.

但我期待的输出是:

server
username
password
dbname
There were 4 tokens found.

请在我错过的地方帮助我。提前致谢

【问题讨论】:

  • 同样,您的输入字符串文字中有一个多余的反斜杠。请提供您正在处理的文字字符串。除了例子,请制定口头规则进行提取。一旦你这样做了,你就不必问几乎相同的问题了。
  • 更改您的正则表达式,使其匹配您想要提取的内容,而不是您想要丢弃的内容。您可以使用捕获组或环视。
  • 简短问题:如果您使用的是std::regex 而不是boost::regex,为什么这个标签是boost?还是我错过了什么?
  • @muXXmit2X 在我的代码中 sregex_token_iterator 属于 boost 。这就是我使用的原因。
  • @WiktorStribiżew 我的表述非常好,究竟是什么预期的,我认为没有多余的反斜杠。这就是我的输入的样子

标签: c++ regex string


【解决方案1】:

出于spite的遗憾,这里是基于上一个答案的解决方案:
extract a string with single quotes between parenthesis and single quote

main 更改为:

int main() {
    auto const text = "server ('m1.labs.terad  ''ata.com') username ('us\\* er5') password('user)5') dbname ('def\\ault')";

    Config cfg = parse_config(text);

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

打印

dbname
password
server
username

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;

    namespace {
        template <typename T> struct as_type {
            template <typename Expr>
            auto operator[](Expr expr) const { return rule<struct _, T>{"as"} = expr; }
        };

        template <typename T> static const as_type<T> as = {};
    }
    auto quoted = [](char q) { return lexeme[q >> *(q >> char_(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() {
    auto const text = "server ('m1.labs.terad  ''ata.com') username ('us\\* er5') password('user)5') dbname ('def\\ault')";

    Config cfg = parse_config(text);

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

打印

dbname
password
server
username

【讨论】:

  • 注意:我解决了您在使用旧 (GCC) 编译器时可能遇到的问题。我从 older answer 中提取了更详细的 as&lt;&gt;[] 指令,因为我注意到某些版本的 GCC 在编译 lambda 版本时出现问题。
  • 如果您拒绝 Spirit 方法是基于不言而喻的要求,那么在 C++03 中也是如此。你的编译器可以处理! coliru.stacked-crooked.com/a/f9f2fcc1bdd2a384
猜你喜欢
  • 2020-12-17
  • 1970-01-01
  • 2017-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-15
  • 2023-03-10
  • 1970-01-01
相关资源
最近更新 更多