【问题标题】:extract a string with single quotes between parenthesis and single quote在括号和单引号之间提取带有单引号的字符串
【发布时间】:2017-07-21 14:10:45
【问题描述】:

我有以下代码:

  #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("(\'(.*?)\'\)");
    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;
}

上面的正则表达式用于提取单引号之间的所有内容。

但是我怎样才能使正则表达式能够提取转义的单引号(例如用户名(user''5)应该被提取为'user'5'。

提前致谢。我真的需要帮助。试了这么多天。

例子

'm1.labs.terad  ata.com'
'us er5'
'user)5'
'def\ault'

找到了 4 个令牌。请注意,字符串周围的单引号应该在那里。提前感谢您的帮助。

但是现在如果我的字符串是

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

输出应该是:

   'm1.labs.terad  ata.com'
    'us 'er5'   <<<<<<<<<<<<<<<<<<<
    'user)5'
    'def\ault'

【问题讨论】:

  • 这可能不是最好的正则表达式匹配,正则表达式只能匹配那里的内容,所以一旦你开始进入更改字符串值的领域,你就超出了范围匹配模式。您可能希望使用某种替换正则表达式,例如 replace(\\\\, \\),但我对 c++ 不够熟悉,无法帮助您。
  • 请试试这个regex re("(\\'.*?[^\\\\]\\')");。另外,请注意,您需要转义 c++ 字符串中的反斜杠。
  • @ikleschenkov 如果我不清楚,我很抱歉。但我想通过添加两个双引号来转义单引号。即'user''6'应该是'user'6'
  • @hydra123 您能否编辑您的问题以显示,输入行应该是什么(我没有在其中看到'user''6')以及您想要得到什么结果?是否要提取单引号之间的所有字符串并将双单引号转换为单单引号?
  • ( &lt;-- Unbalanced '(' \' ( .*? ) \'\) 解析 C++ 双引号字符串只会在转义时移除转义。你的正则表达式不应该编译。

标签: c++ regex boost


【解决方案1】:

但是我怎样才能使正则表达式能够提取转义的单引号(例如用户名(user''5)应该被提取为'user'5'。

呃。那是you meant吗?然后我was right 关于 X/Y 问题。

注意:您所描述的称为转义特殊字符。两种常见的特殊字符转义方式:

  1. 重复它(例如printf("100%%");打印100%
  2. 使用另一个转义符(通常是反斜杠)引入它。例如。

    std::cout << "Hello \"World\"" << std::endl;
    

    或者,再举一个复杂的例子:

    std::cout << "Newline is \\n" << std::endl;
    

给你:只需添加 q &gt;&gt; char_(q) 以接受重复引号作为引号转义:

auto quoted = [](char q) { 
    return lexeme[ q >> *(
              q >> char_(q)  // accept repeated quotes as quote-escape
            | '\\' >> char_  // accept backs-slash escape
            | char_ - q      // accept any other non-quote
         ) >> q]; };

相对于tokenizing string , accepting everything between given set of characters in CPP,没有其他变化

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 = [](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.teradata.com') username ('use'')r_*5') password('u\" er 5') dbname ('default')";
    Config cfg = parse_config(text);

    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

【讨论】:

    【解决方案2】:

    您应该查看 look-aroundconditional 正则表达式。
    并且正则表达式引擎应该是 PCRE 兼容的。 (我不懂 C++)

    你应该更新使用正则表达式,如果你不明白,你在互联网上找到了。

    尝试类似'((?:[^']|'')*?)'(?!') (demo on 101regex)

    【讨论】:

    • C++ 正则表达式不兼容 PCRE,很遗憾。
    • 但是,实际上有外部库,不是吗? (例如:增强正则表达式)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-29
    • 1970-01-01
    • 2017-03-28
    • 2017-02-26
    • 1970-01-01
    相关资源
    最近更新 更多