1

总结一下:如何防止我的正则表达式模式将字符串段误认为是全字变量名?即使我使用单词边界,它也正在替换作为更大单词一部分的字母\b

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

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

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

我所拥有的:这是我的正则表达式模式:\b([a-z][a-z0-9_]*)\b这不应该只匹配整个单词吗?单词边界工作正常,直到 '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

4

1 回答 1

2

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

问题是我在正则表达式匹配之后使用了基本的字符串替换,所以单词边界有效,只是字符串替换函数正在替换字符串的每次出现,而不管单词边界如何。我必须使用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;
}
于 2012-10-03T07:18:23.913 回答