Regex-Word边界失败

Regex - Word boundaries failing

本文关键字:失败 边界 Regex-Word      更新时间:2023-10-16

总结一下:如何防止regex模式将字符串段误认为是一个完整的单词变量名?即使我使用单词边界b,它也会替换较大单词中的字母。

我想做的事:我正在做一个计算器。它有一个变量列表,在将表达式传递给解析器之前,我调用函数ParseVars(),使用变量匹配模式来执行regex_search。一旦它拥有了与我的变量模式匹配的所有标记,我就会检查该字符串是否真的在变量名列表中,如果是,我会用变量值替换该字符串。此外,每次在解析器中进行计算时,我都会定义一个名为ans1ans2等的常量

问题是:假设我定义了一个变量,名为a,其值为6。(顺便说一句,我在map<string,double> Vars;中跟踪这些。当我执行ParseVars("answers1")时,得到的字符串是"answers1"。同样对于ParseVar(),字符串ans1+ans2+9保持不变。字符串9+a变为9+6。因此,到目前为止,我的正则表达式按预期工作。

但是,如果我执行ParseVars("answers1+a"),则结果字符串为"6ns1+6"。我很困惑,为什么只有当我使用变量"a"时,正则表达式上的单词边界才会失败,"a"总是可以在"answers1"中找到,但只有当"a"在字符串中的其他地方单独存在时,它才会被替换。

我有什么:这是我的正则表达式模式:b([a-z][a-z0-9_]*)b这不应该只匹配整个单词吗?单词boundary可以正常工作,直到字符串中的其他地方只有"a"。也许是我的ParseVars()函数,这是代码:

map<string,double> Vars;
// Variables must be a whole word, start with a letter, and
// optionally have other letters, numbers, and underscores.
sregex VarPattern = sregex::compile("\b([a-z][a-z0-9_]*)\b");
string Calculator::ParseVars(string expr) {
if (Vars.empty()) return expr;
string newExpr = StrToLower(expr);
const sregex_iterator End;
// Loop through all possible variable matches
for (sregex_iterator i(expr.begin(), expr.end(), VarPattern); i != End; ++i) {
string name = (*i)[0];
// If it is a variable
if (Vars.find(name) != Vars.end()) {
int rPos = 0;
// Replace all occurrences of it
while ((rPos = newExpr.find(name, rPos)) != string::npos) {
newExpr.replace(
rPos, name.length(),
lexical_cast<string,double>(Vars[name])
);
}
}
}
return newExpr;
}

a等于6的情况下,如何防止ans1+a变成6ns1+6而不是所需的ans1+6

好吧,我找到了解决方案。我在这里为遇到类似问题的人提供答案。

问题是,在正则表达式匹配后,我使用了一个基本的字符串替换,所以单词边界有效,只是字符串替换函数替换了字符串的每一个出现,而不考虑单词边界。我必须使用regex_replace(),这是我最终得到的:

map<string,double> Vars;
// Variables must be a whole word, start with a letter, and
// optionally have other letters, numbers, and underscores.
sregex VarPattern = sregex::compile("\b([a-z][a-z0-9_]*)\b");
string Calculator::ParseVars(string expr) {
if (Vars.empty()) return expr;
string newExpr = StrToLower(expr);
const sregex_iterator End;
// Loop through all possible variable matches
for (sregex_iterator i(expr.begin(), expr.end(), VarPattern); i != End; ++i) {
string name = (*i)[0];
// If it is a variable
if (Vars.find(name) != Vars.end()) {
sregex rgxName = sregex::compile("\b" + name + "\b");
// Replace all occurrences of it
newExpr = xpressive::regex_replace(
newExpr, rgxName,
lexical_cast<string,double>(Vars[name])
);
}
}
return newExpr;
}