将数学表达式与正则表达式匹配? [英] Matching math expression with regular expression?

查看:96
本文介绍了将数学表达式与正则表达式匹配?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

例如,以下是有效的数学表达式:

For example, these are valid math expressions:

a * b + c
-a * (b / 1.50)
(apple + (-0.5)) * (boy - 1)

这些是无效的数学表达式:

And these are invalid math expressions:

--a *+ b @ 1.5.0  // two consecutive signs, two consecutive operators, invalid operator, invalid number
-a * b + 1)  // unmatched parentheses
a) * (b + c) / (d  // unmatched parentheses

我对匹配浮点数没有问题,但是对括号匹配有困难.任何的想法?如果有比正则表达式更好的解决方案,我也会接受.但是正则表达式是首选.

I have no problem with matching float numbers, but have difficulty with parentheses matching. Any idea? If there is better solution than regular expression, I'll accept as well. But regex is preferred.

========

我想对我选择的可接受的答案"发表一些评论,希望那些有相同问题并找到该线索的人不会被误导.

I want to make some comments on my choice of the "accepted answer", hoping that people who have the same question and find this thread will not be misled.

我认为有几个答案可以接受,但是我不知道哪个是最好的.因此,我(几乎)随机选择了可接受的答案.除了建议的答案,我还建议您阅读Guillaume Malartre的答案.所有这些都为我的问题提供了切实可行的解决方案.要获得较为严格/理论上的答案,请阅读公认的答案下戴维·桑利(David Thornley)的评论.正如他提到的,Perl对正则表达式的扩展(起源于正则语言)使其变得不规则". (我没有在问题中提到任何语言,因此大多数回答者都假设使用正则表达式的Perl实现-可能是最受欢迎的实现.发布问题时也是如此.)

There are several answers I consider "accepted", but I have no idea which one is the best. So I chose the accepted answer (almost) randomly. I recommend reading Guillaume Malartre’s answer as well besides the accepted answer. All of them give practical solutions to my question. For a somewhat rigorous/theoretical answer, please read David Thornley’s comments under the accepted answer. As he mentioned, Perl’s extension to regular expression (originated from regular language) make it "irregular". (I mentioned no language in my question, so most answerers assumed the Perl implementation of regular expression – probably the most popular implementation. So did I when I posted my question.)

如果我在上面说错了,请纠正我.

Please correct me if I said something wrong above.

推荐答案

使用正则表达式匹配parens是很有可能的.

Matching parens with a regex is quite possible.

这是一个Perl脚本,它将解析任意深度匹配的括号.虽然它将排除不匹配的parens,但我并不是专门设计用于验证parens的.只要它们是平衡的,它将解析任意深度的paren.但是,这将使您入门.

Here is a Perl script that will parse arbitrary deep matching parens. While it will throw out the non-matching parens outside, I did not design it specifically to validate parens. It will parse arbitrarily deep parens so long as they are balanced. This will get you started however.

关键在于正则表达式及其使用中的递归.试一试,我相信您也可以标记不匹配的前哨.我认为,如果您捕获了此正则表达式丢弃的内容并计算了括号(即,在不匹配文本中测试奇数括号),则您将拥有无效,不平衡的括号.

The key is recursion both in the regex and the use of it. Play with it, and I am sure that you can get this to also flag non matching prens. I think if you capture what this regex throws away and count parens (ie test for odd parens in the non-match text), you have invalid, unbalanced parens.

#!/usr/bin/perl
$re = qr  /
     (                      # start capture buffer 1
        \(                  #   match an opening paren
        (                   # capture buffer 2
        (?:                 #   match one of:
            (?>             #     don't backtrack over the inside of this group
                [^()]+    #       one or more 
            )               #     end non backtracking group
        |                   #     ... or ...
            (?1)            #     recurse to opening 1 and try it again
        )*                  #   0 or more times.
        )                   # end of buffer 2
        \)                  #   match a closing paren
     )                      # end capture buffer one
    /x;


sub strip {
    my ($str) = @_;
    while ($str=~/$re/g) {
        $match=$1; $striped=$2;
        print "$match\n";
        strip($striped) if $striped=~/\(/;
        return $striped;
    }
}

while(<DATA>) {
    print "start pattern: $_";
    while (/$re/g) { 
        strip($1) ;
    }
}   

__DATA__
"(apple + (-0.5)) * (boy - 1)"
"((((one)two)three)four)x(one(two(three(four))))"
"a) * (b + c) / (d"
"-a * (b / 1.50)"

输出:

start pattern: "(apple + (-0.5)) * (boy - 1)"
(apple + (-0.5))
(-0.5)
(boy - 1)
start pattern: "((((one)two)three)four)x(one(two(three(four))))"
((((one)two)three)four)
(((one)two)three)
((one)two)
(one)
(one(two(three(four))))
(two(three(four)))
(three(four))
(four)
start pattern: "a) * (b + c) / (d"
(b + c)
start pattern: "-a * (b / 1.50)"
(b / 1.50)

这篇关于将数学表达式与正则表达式匹配?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆