Skip to main content
 首页 » 编程设计

c#之如何在没有正则表达式的情况下模拟正则表达式后视

2024年04月18日41lyj

我正在使用 C# 开发一个项目,出于某种原因,该项目正慢慢从使用正则表达式过渡,但到目前为止,实现它一直很痛苦。

具体来说,我需要检查数学表达式中的一元运算符,这可能会在直接字符串搜索中与二元运算符混淆。


现在,项目的正则表达式看起来像这样:

(?<=(?:<<|>>|\+|-|\*|\/|%|&&|\|\||&|\||\^|==|!=|<>|>=|=>|<=|=<|=|<|>)\s*|\A)(?:(?:\+|-|!|~)(?=\w|\()) 

本质上,它会在假定运算符是一元运算符之前先查找二元运算符。

当前试图替换该正则表达式的代码看起来与此类似:

private static readonly string[] _unaryOps = new string[] { "+", "-", "!", "~" }; 
 
private string MatchUnaryOp(string expr, int index) 
{ 
    int foundIndex = int.MaxValue; // so currentIndex always starts out less than foundIndex 
    string foundOp = null; 
    foreach (string op in _unaryOps) { 
        int currentIndex = expr.IndexOf(op, index); 
        if (currentIndex > -1 && currentIndex < foundIndex) { 
            foundIndex = currentIndex; 
            foundOp = op; 
        } 
    } 
    return foundOp; 
} 

问题是这段代码显然没有考虑到后视,它最终错误地将模棱两可的二元运算符 (+,-) 标记为一元。如何在没有正则表达式的情况下模拟后视?

编辑: 如果这个问题看起来过于宽泛,我只是要求一个更恰本地模拟原始正则表达式所做的事情的解决方案。只要它可以模拟特定的正则表达式,我就可以使用它。


编辑 2: 上面的正则表达式目前匹配这样的运算符:

5 + -10 
    ^ this minus sign matches the conditions in the regex 

但是,上面的代码目前匹配:

5 + -10 
  ^ the plus sign is incorrectly assumed to be unary 

我想知道是否有可行的方法来解析这个简单的表达式。简单地确定减号是一元的,而加号不是。有没有好的方法来实现这个?可能通过像这样循环遍历数组中的二进制操作?

private static readonly string[] _binaryOps = new string[] { "<<", ">>", "+", "-", "*", "/", "%", "&&", "||", "&", "|", "^", "==", "!=", "<>", ">=", "=>", "<=", "=<", "=", "<", ">" }; 

请您参考如下方法:

与其从头开始创建解析引擎来重新发明轮子,不如重写正则表达式以完全按照您的要求进行操作,或者提供有关您要构建的算法的更多详细信息,完成有更详尽的例子。

你的表情

(?<=(?:<<|>>|\+|-|\*|\/|%|&&|\|\||&|\||\^|==|!=|<>|>=|=>|<=|=<|=|<|>)\s*|\A)(?:(?:\+|-|!|~)(?=\w|\())

Regular expression visualization

您的正则表达式可以通过用字符类替换一些交替并创建树状结构来提高效率。这将显着减少正则表达式引擎所做的回溯量。

如果交替到达 \A那么在尝试匹配 (?:(?:\+|-|!|~)(?=\w|\()) 时表达式将失败.这是因为 \A表示字符串的结尾,因此根据定义,结尾之后不能再有任何内容。

简化版

此简化版本的功能与您的表达式相同,但工作量更少。请记住 \A这里仍然会像上面一样导致匹配失败。

(?<=(?:([&|<>=])\1|[-+*\/%&|^=<>]|!=|>=|=[<>]|<[>=])\s*|\A)(?:[-+!~](?=[\w(])) 

Regular expression visualization