用单引号(')替换双引号('')

时间:2017-07-24 04:45:22

标签: c++ string boost replace

假设我有一个字符串:

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

现在我使用以下代码来提取令牌:

'm1.labs.terad  ''ata.com'  <- token1
'us ''er5'                    <-token2
'user)5'                    <-token3
'def\ault'                  <-token4

代码:

regex re("(\'(.*?)\'\)");
typedef std::vector<std::string> StringVector;
StringVector arg_values;
boost::regex re_arg_values("('[^']*(?:''[^']*)*')");
boost::sregex_token_iterator name_iter_start(argsStr.begin(),argsStr.end(), re_arg_values, 0),name_iter_end;
std::copy(value_iter_start, value_iter_end,std::back_inserter(arg_values)); 
//putting the token in the string vector.

现在将它放入字符串向量后,如何转换标记/字符串以用单引号替换双引号:

例如:

'm1.labs.terad ''ata.com'应该成为'm1.labs.terad 'ata.com'和  'us ''er5'应该成为'us 'er5'

我可以使用boost :: replace_all吗?

2 个答案:

答案 0 :(得分:7)

好。您已经直接询问了6个问题的解析工作。

许多人一直在告诉你,正则表达不是工作的工具。 Including me

  

enter image description here

我告诉你了

  • Spirit X3语法示例,将此配置字符串解析为键值映射,正确解析转义引号('\\''例如)(请参阅here
  • 我对其进行了扩展(以13个字符开头)以允许重复引用以逃避引用(请参阅here

我的所有示例都非常出色,因为它们已经解析了键和值,因此您有一个合适的配置设置图。

但你仍然在最新的问题(Extract everything apart from what is specified in the regex)中提出这个问题。

当然答案是我的第一个答案:

for (auto& setting : parse_config(text))
    std::cout << setting.first << "\n";

posted this以及它的C ++ 03版本live on Coliru

编写手动解析器

如果你因为不理解而拒绝它,你所要做的就是问。

如果你“不想”使用Spirit,你可以轻松地手动编写类似的解析器。我没有,因为它很乏味且容易出错。在这里,如果您需要灵感,请在这里:

  1. 仍然是c ++ 03
  2. 仅使用标准库功能
  3. 仍在解析带有可逃避引号的单/双引号字符串
  4. 仍然会解析为map<string, string>
  5. 在无效输入上提出信息性错误消息
  6.   

    BOTTOM LINE :使用正确的语法,就像人们从第1天起就一直在催促你

    <强> Live On Coliru

    #include <iostream>
    #include <sstream>
    #include <map>
    
    typedef std::map<std::string, std::string> Config;
    typedef std::pair<std::string, std::string> Entry;
    
    struct Parser {
        Parser(std::string const& input) : input(input) {}
        Config parse() {
            Config parsed;
    
            enum { KEY, VALUE } state = KEY;
            key = value = "";
            f = input.begin(), l = input.end();
    
            while (f!=l) {
                //std::cout << "state=" << state << ", '" << std::string(It(input.begin()), f) << "[" << *f << "]" << std::string(f+1, l) << "'\n";
                switch (state) {
                  case KEY:
                      skipws();
                      if (!parse_key())
                          raise("Empty key");
    
                      state = VALUE;
                      break;
                  case VALUE:
                      if (!expect('(', true))
                          raise("Expected '('");
    
                      if (parse_value('\'') || parse_value('"')) {
                          parsed[key] = value;
                          key = value = "";
                      } else {
                          raise("Expected quoted value");
                      }
    
                      if (!expect(')', true))
                          raise("Expected ')'");
    
                      state = KEY;
                      break;
                };
            }
    
            if (!(key.empty() && value.empty() && state==KEY))
                raise("Unexpected end of input");
    
            return parsed;
        }
    
      private:
        std::string input;
    
        typedef std::string::const_iterator It;
        It f, l;
        std::string key, value;
    
        bool parse_key() {
            while (f!=l && alpha(*f))
                key += *f++;
            return !key.empty();
        }
    
        bool parse_value(char quote) {
            if (!expect(quote, true))
                return false;
    
            while (f!=l) {
                char const ch = *f++;
                if (ch == quote) {
                    if (expect(quote, false)) {
                        value += quote;
                    } else {
                        //std::cout << " Entry " << key << " -> " << value << "\n";
                        return true;
                    }
                } else {
                    value += ch;
                }
            }
    
            return false;
        }
    
        static bool space(unsigned char ch) { return std::isspace(ch); }
        static bool alpha(unsigned char ch) { return std::isalpha(ch); }
        void skipws() { while (f!=l && space(*f)) ++f; }
        bool expect(unsigned char ch, bool ws = true) {
            if (ws) skipws();
            if (f!=l && *f == ch) {
                ++f;
                if (ws) skipws();
                return true;
            }
            return false;
        }
    
        void raise(std::string const& msg) {
            std::ostringstream oss;
            oss << msg << " (at '" << std::string(f,l) << "')";
            throw std::runtime_error(oss.str());
        }
    };
    
    int main() {
        std::string const text = "server ('m1.labs.terad  ''ata.com') username ('us\\* er5') password('user)5') dbname ('def\\ault')";
    
        Config cfg = Parser(text).parse();
    
        for (Config::const_iterator setting = cfg.begin(); setting != cfg.end(); ++setting) {
            std::cout << "Key " << setting->first << " has value " << setting->second << "\n";
        }
    
        for (Config::const_iterator setting = cfg.begin(); setting != cfg.end(); ++setting) {
            std::cout << setting->first << "\n";
        }
    }
    

    一如既往地打印:

    Key dbname has value def\ault
    Key password has value user)5
    Key server has value m1.labs.terad  'ata.com
    Key username has value us\* er5
    dbname
    password
    server
    username
    

    ¹见

    1. avoid empty token in cpp
    2. extracting whitespaces using regex in cpp
    3. Regex to extract value between a single quote and parenthesis using boost token iterator
    4. tokenizing string , accepting everything between given set of characters in CPP
    5. extract a string with single quotes between parenthesis and single quote
    6. Extract everything apart from what is specified in the regex
    7. 这个

答案 1 :(得分:-1)

使用For循环替换字符串中的子字符串

这里我们用另一个子串替换子串并返回修改后的字符串。我们传入要更改的字符串,我们想要查找的字符串以及我们要用ss_to_replaces_replace替换它的字符串。

find()搜索并找到传入的字符串的第一个字符,并在该位置返回一个迭代器。 std::string::npos此值是可能达到的最大值size_t,即字符串的结尾。 std::string::erase取代第一个字符的位置和要替换的字符数并删除它们。 std::string::insert获取插入位置和要插入的字符串的位置,并执行此操作。

std::string replace_substring(string s, const string s_to_replace, const string s_replace) {
    for(size_t position = 0; ; position += s_replace.length()) {

        position = s.find(s_to_replace, position);

        if(position == string::npos || s.empty()) break;

        s.erase(position, s_to_replace.length());
        s.insert(position, s_replace);
        // s.replace(position, s_to_replace.length(), s_replace)
    }
    return s;
}

使用Boost

将子字符串替换为字符串中的子字符串
#include <boost/algorithm/string/replace.hpp>

boost::replace_all(s, s_to_replace, s_replace);