Suppose I have a string :
argsStr = "server ('m1.labs.terad ''ata.com') username ('us ''er5') password('user)5') dbname ('def\\ault')";
Now I am using the following code to extract the 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 after putting it into the string vector, How can I convert the tokens/ string to replace double quotes with single quotes:
For example:
'm1.labs.terad ''ata.com'
should become 'm1.labs.terad 'ata.com'
and
'us ''er5'
should become 'us 'er5'
.
Can I use boost::replace_all for this?
Okay. You've been asking about this parsing jobs for 6 questions straight¹.
Many people have been telling you regex is not the tool for the job. Including me:
I've shown you
'\\''
e.g.) (see here)All my examples have been superior in that they already parse the keys along with the values, so you have a proper map of config settings.
Yet you still ask for it in you latest question (Extract everything apart from what is specified in the regex).
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 a C++03 version of it live on Coliru
If you are rejecting it because you don't understand, all you had to do is ask.
If you "don't wanna" use Spirit, you can easily write a similar parser manually. I didn't, because it is tedious and error prone. Here you are in case you need it for inspiration:
map<string, string>
BOTTOM LINE: Use a proper grammar like people have been urging you since day 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";
}
}
Prints, 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With