简写版本

我正在使用此正则表达式:

(^|[yY]\s{0,}\=|\+|\-)\s{0,}([0-9]{0,}\.?[0-9]{0,})\s{0,}(\*{0,1}[xX]{0,1})\s{0,}(\^{0,1})(-?)([0-9]{0,}\.?[0-9]{0,})(\s{0,}|$)?

要尝试从等式中提取所有元素系数和阶数:
y=x+3.3X^-50+ 15x25.5 - 4x^+2x^2 +3*x-2.5+1.1

我希望正则表达式忽略错误的4x^,它丢失了其电源编号(当前不执行此操作),并允许我得出以下最终结果:
((1.0, 1.0), (3.3, -50.0), (15.0, 25.5), (2.0, 2.0), (3.0, -3.5), (1.1, 0.0))

第一个坐标是系数,第二个坐标是每个元素的阶数。目前,如果我采用组1&2和5&6分别给我系数和阶数,则“接近”上方的正则表达式有效。

它只是落在错误的4x^之上,而且感觉极其不雅,但是我对regex有点陌生,并且不确定要进行哪些改进。

我如何改善此正则表达式,并进行修复,以便将4x^视为“错误”,但是4x24x^2都很好?

tl;博士版本

我正在尝试解析用户输入的多项式方程,以进行验证,然后将其分解为一系列元素。这些方程式将以字符串形式显示。

这是有关如何要求用户格式化其字符串的示例:
y = 2.0x^2.5 - 3.1x + 5.2

其中x是自变量(不是时间符号),而y是因变量。

实际上,用户通常会犯以下任何错误:
  • 忘记包括y =
  • *添加到诸如y = 2.0*x的系数
  • 使用整数代替浮点数,例如y = 5x
  • 设置顺序时缺少^,例如y = x3
  • 的任何地方添加或删除空格

    但是,对于所有这些,我想说用户尝试编写的内容仍然很容易理解。我的意思是很明显,每个元素的系数和阶数是什么意思。

    因此,我想做的是编写一些正则表达式,将输入的字符串正确地拆分为单独的元素,并让我获得每个元素的A(系数)和B(顺序),其中元素的形式通常为Ax^BAB可以是任何实数。

    我设计了以下示例:
    y=x+3.3X^-50+ 15x25.5 - 4x^+2x^2 +3*x-2.5+1.1
    

    我相信它涵盖了我上面概述的所有潜在问题,此外还有一个直接错误4x^+2x^2缺少元素4x^上的顺序。

    对于此示例,我想访问:((1.0, 1.0), (3.3, -50.0), (15.0, 25.5), (2.0, 2.0), (3.0, -3.5), (1.1, 0.0))其中4x^被忽略了。

    我对regex有点陌生,但是我已经使用regex101.com进行了以下工作:
    (^|[yY]\s{0,}\=|\+|\-)\s{0,}([0-9]{0,}\.?[0-9]{0,})\s{0,}(\*{0,1}[xX]{0,1})\s{0,}(\^{0,1})(-?)([0-9]{0,}\.?[0-9]{0,})(\s{0,}|$)?
    

    似乎几乎可以解决以下问题:
  • 不会像上面给出的示例4x^那样捕获丢失的订单-我不确定如何在存在^的情况下使订单号的可选性“有条件”,而在没有^但订单号为y = 4x2的情况下也可以工作
  • 感觉非常简洁/优雅,但是由于经验不足,我正在努力寻找可以在哪里进行改进的地方

  • 另外请注意,我很高兴地忽略了没有求和相同顺序的重复元素的问题,例如我很乐意忽略y = x^2 + x^2不会显示为y = 2x^2

    感谢您的任何帮助。

    ps用Go编写的程序,但是我在Go上也有点菜鸟,所以我首先用Python进行原型(prototype)设计。不知道这是否会对正则表达式产生任何影响(我真的是正则表达式的新手)。

    最佳答案

    以下正则表达式主要用于:

    (?P<c1>[+-]? *\d+(?:\.\d+)?)? *\*? *[xX] *(?:\^ *(?P<e1>-? *\d+(?:\.\d+)?)|(?P<e2>-? *\d+(?:\.\d+)?)?)|(?P<c2>[+-]? *\d+(?:\.\d+)?)
    

    我之所以这么说,主要是因为该解决方案将“4x ^”的情况视为第1阶,因为要求已经非常宽松,否则尝试忽略该术语会使RE变得更加复杂甚至不可能,因为这会造成歧义用RE解析。

    请注意,缺少的系数/指数将不会像您在示例结果中所表示的那样被捕获为“1.0”,这必须在应用正则表达式并将所有空捕获组作为“1”(或对于“0”表示指数取决于捕获的组)。

    Here you have the regex in regex101.com用于检查/尝试其工作方式。

    这是一个使用golang的工作程序,它可以测试几种情况:
    package main
    
    import (
        "fmt"
        "regexp"
        "strconv"
        "strings"
    )
    
    const e = `(?P<c1>[+-]? *\d+(?:\.\d+)?)? *\*? *[xX] *(?:\^ *(?P<e1>-? *\d+(?:\.\d+)?)|(?P<e2>-? *\d+(?:\.\d+)?)?)|(?P<c2>[+-]? *\d+(?:\.\d+)?)`
    
    var cases = []string{
        "y=x+3.3X^-50+ 15x25.5 - 4x^+2x^2 +3*x-2.5+1.1",
        "3.3X^-50",
    }
    
    func parse(d float64, ss ...string) float64 {
        for _, s := range ss {
            if s != "" {
                c, _ := strconv.ParseFloat(strings.Replace(s, " ", "", -1), 64)
                return c
            }
        }
        return d
    }
    
    func main() {
        re := regexp.MustCompile(e)
        for i, c := range cases {
            fmt.Printf("testing case %v: %q\n", i, c)
            ms := re.FindAllStringSubmatch(c, -1)
            if ms == nil {
                fmt.Println("no match")
                continue
            }
            for i, m := range ms {
                fmt.Printf("  match %v: %q\n", i, m[0])
                c := parse(1.0, m[1], m[4])
                de := 1.0
                if m[4] != "" {
                    de = 0.0
                }
                e := parse(de, m[2], m[3])
                fmt.Printf("    c: %v\n", c)
                fmt.Printf("    e: %v\n", e)
            }
        }
    }
    

    哪个输出:
    testing case 0: "y=x+3.3X^-50+ 15x25.5 - 4x^+2x^2 +3*x-2.5+1.1"
      match 0: "x"
        c: 1
        e: 1
      match 1: "+3.3X^-50"
        c: 3.3
        e: -50
      match 2: "+ 15x25.5"
        c: 15
        e: 25.5
      match 3: "- 4x"
        c: -4
        e: 1
      match 4: "+2x^2"
        c: 2
        e: 2
      match 5: "+3*x-2.5"
        c: 3
        e: -2.5
      match 6: "+1.1"
        c: 1.1
        e: 0
    testing case 1: "3.3X^-50"
      match 0: "3.3X^-50"
        c: 3.3
        e: -50
    

    Here you have the program on golang playground试试。

    10-06 13:16