假设我有一个字符串:
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吗?
答案 0 :(得分:7)
好。您已经直接询问了6个问题的解析工作。
许多人一直在告诉你,正则表达不是工作的工具。 Including me:
我告诉你了
我的所有示例都非常出色,因为它们已经解析了键和值,因此您有一个合适的配置设置图。
但你仍然在最新的问题(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,你可以轻松地手动编写类似的解析器。我没有,因为它很乏味且容易出错。在这里,如果您需要灵感,请在这里:
map<string, string>
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 :(得分:-1)
这里我们用另一个子串替换子串并返回修改后的字符串。我们传入要更改的字符串,我们想要查找的字符串以及我们要用s
,s_to_replace
和s_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;
}
#include <boost/algorithm/string/replace.hpp>
boost::replace_all(s, s_to_replace, s_replace);