Replace the double single quote ('') with a single quote (')

Suppose I have a line:

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

Now I use the following code to extract tokens:

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

code:

 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. 

Now, putting it in a string vector, how can I convert tokens / string to replace double quotes with single quotes:

For instance:

'm1.labs.terad ''ata.com' should become 'm1.labs.terad 'ata.com' and 'us ''er5' should become 'us 'er5' .

Is it possible to use boost :: replace_all for this?

+5
source share
2 answers

Replace substring with substring in string using for loop

Here we substitute the substring with another substring and return the modified string. We pass in the string we need to change, the string we want to find, and the string we want to replace, s , s_to_replace and s_replace .

find() performs a search and finds the first character of the passed string and returns an iterator at that position. std::string::npos this value the maximum possible value of size_t can reach, i.e. end of line. std::string::erase takes the position of the first character and the number of characters to replace and erases them. std::string::insert takes the position where you want to insert, and the line to be inserted does exactly that.

 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; } 

Replace substring with substring in string using Boost

 #include <boost/algorithm/string/replace.hpp> boost::replace_all(s, s_to_replace, s_replace); 
-1
source

Good. You asked a question about these syntactic tasks on 6 questions directly.

Many people have told you that regular expression is not a tool for work. Including me :

enter image description here

I showed you

  • An example of a Spirit X3 grammar that parses this configuration line in a key value map, correctly interpreting escaped quotes ( '\\'' eg) (see here )
  • I expanded it (in 13 characters) to allow repeated quotes to avoid quotation (see here )

All my examples were excellent in that they already parse the keys along with the values, so you have the right map of configuration settings.

However, you still ask for it in your last question ( Extract everything except what is indicated in the regular expression ).

Of course, the answer was in my very first answer:

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

I posted this along with my C ++ 03 version live on Coliru

Writing a Handheld Analyzer

If you reject it because you do not understand, all you have to do is ask.

If you don't want to use Spirit, you can easily write a similar parser manually. I did not do this because it is tiring and error prone. Here you are in case you need it for inspiration:

  • more C ++ 03
  • using only standard library functions
  • still parsing single / double quotes with escalation quotes
  • still parsing on map<string, string>
  • causes informative error messages when invalid input

BOTTOM LINE : Use the correct grammar as people have been calling you from day one.

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"; } } 

Printing, as always:

 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 

ยน see

+7
source

Source: https://habr.com/ru/post/1270128/


All Articles