简短版
我正在使用这个正则表达式:
(^|[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^
加上感觉非常不优雅,但我在正则表达式上有些不高兴,并且不确定要做出哪些改进。
如何改进此正则表达式,并进行修正,以便4x^
被视为错误'但是4x2
和4x^2
都很好吗?
tl; dr version
我正在尝试用户输入的解析多项式方程,以便验证然后将方程式分解为一系列元素。方程将以字符串形式呈现。
以下是如何要求用户格式化其字符串的示例:
y = 2.0x^2.5 - 3.1x + 5.2
其中x
是自变量(不是时间符号),y
是因变量。
实际上,用户通常会犯以下错误:
y =
*
添加到y = 2.0*x
y = 5x
^
,例如y = x3
然而,对于所有这些,我说它仍然很容易理解用户试图写什么。我的意思是,显然每个元素的系数和顺序是什么。
所以我想做的是写一些正则表达式,正确地将输入的字符串拆分成单独的元素,并且可以得到每个元素的A
(系数)和B
(顺序)一般来说,元素的格式为Ax^B
,A
和B
可以是任何实数。
我设计了以下示例:
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
。
感谢您的帮助。
P.S。要用Go编写的程序,但我在Go中也是一些菜鸟,所以我首先在Python中进行原型设计。不确定这是否会对正则表达式产生任何影响(我真的是正则表达式的新手)。
答案 0 :(得分:1)
以下正则表达式主要是:
(?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