正则表达式挑战:改变负数格式

时间:2017-02-10 15:04:19

标签: c# regex parsing replace

首先,我认为我必须为没有那么多正则表达式的知识而道歉(还)。 我搜索过并搜索过,但未找到符合我特定挑战的解决方案。

现在问题出现了:

我目前正在尝试开发解析器(意思是自己编写)。我想在考虑正则表达式时这样做。 到目前为止,我已经设法做了很多,但是,我遇到了一个小问题。一元减号和二进制减号。

我十年前在大学学到的是,这应该基于背景。然而,还有一个简单的技巧,我在手工操作时使用它,并将每个一元减去写入不同的格式:

-3 = (0 - 3) 

5 * -3 = 5 * (0 - 3)

有点棘手:

(5--5)-3 = (5 - (0 - 5)) - 3

现在,我的问题是,是否有可能编写一个正则表达式,通过添加括号将一元减号表达式转换为二进制减去表达式和0 一样,如上面提供的例子那样?

也许可能还有另一种方式,但我在这里有点偏见......

注释: 首先,我开始用MINUS替换所有减号,如:

expressionBuffer = "-(1-2)-3";
expressionBuffer = Regex.Replace(expressionBuffer, "-", "MINUS");

这会产生一个新的expressionBuffer,它看起来像:

MINUS ( 1 MINUS 2 ) MINUS 3

现在,我尝试捕获二进制文件' - '运算符应用以下正则表达式:

expressionBuffer = Regex.Replace(
                     expressionBuffer, 
                     @"(?<number>((\d+(\.\d+)?)))\s+MINUS", 
                     "${number} -"
                   );

这会产生:

MINUS ( 1 - 2 ) MINUS 3

第一个MINUS显然是一个一元的运算符(但第二个显然不是!)所以我现在正在寻找一种方法来重写那个(first)格式:

( 0 - ( 1 - 2) ) MINUS 3

但在这里,我坚持将第一个一元减号视为二元减号,以便:

( 0 - ( 1 - 2) ) - 3

关于如何使用正则表达式的任何想法?

1 个答案:

答案 0 :(得分:3)

是的,你可以这样做,但只要有变化就要调用替换操作,因为以下正则表达式只会替换一个单一的运算符:

private static Regex _regex = new Regex(@"(?<=^|[-(+*/])-(?<value>\d+|\((?:[^\(\)]|(?<open>\()|(?<-open>\)))+?(?(open)(?!))\))", RegexOptions.Compiled);

private static string RemoveUnaryOperators(string input)
{
    var result = Regex.Replace(input ?? string.Empty, @"\s+", string.Empty);
    string tmp;
    do
    {
        tmp = result;
        result = _regex.Replace(result, @"(0-${value})");
    }
    while (result != tmp);

   return result;
}

DEMO

输出:

5*-3  ->  5*(0-3)
(5--5)-3  ->  (5-(0-5))-3
(5-------5)-3  ->  (5-(0-(0-(0-(0-(0-(0-5)))))))-3
-(1-2)-3  ->  (0-(1-2))-3