【发布时间】:2021-06-21 12:33:27
【问题描述】:
为了一个有趣的练习,我想知道是否可以使用正则表达式标记简单的算术表达式(仅包含正整数和四个基本运算),所以我想出了以下内容:
但由于最后列出的故障 (Go Playground),下面的测试用例的行为与我预期的不同:
func TestParseCalcExpression(t *testing.T) {
re := regexp.MustCompile(`^(\d+)(?:([*/+-])(\d+))*$`)
for _, eg := range []struct {
input string
expected [][]string
}{
{"1", [][]string{{"1", "1", "", ""}}},
{"1+1", [][]string{{"1+1", "1", "+", "1"}}},
{"22/7", [][]string{{"22/7", "22", "/", "7"}}},
{"1+2+3", [][]string{{"1+2+3", "1", "+", "2", "+", "3"}}},
{"2*3+5/6", [][]string{{"2*3+5/6", "2", "*", "3", "+", "5", "/", "6"}}},
} {
actual := re.FindAllStringSubmatch(eg.input, -1)
if !reflect.DeepEqual(actual, eg.expected) {
t.Errorf("expected parse(%q)=%#v, got %#v", eg.input, eg.expected, actual)
}
}
}
// === RUN TestParseCalcExpression
// prog.go:24: expected parse("1+2+3")=[][]string{[]string{"1+2+3", "1", "+", "2", "+", "3"}}, got [][]string{[]string{"1+2+3", "1", "+", "3"}}
// prog.go:24: expected parse("2*3+5/6")=[][]string{[]string{"2*3+5/6", "2", "*", "3", "+", "5", "/", "6"}}, got [][]string{[]string{"2*3+5/6", "2", "/", "6"}}
// --- FAIL: TestParseCalcExpression (0.00s)
// FAIL
我希望识别和分组运算符和数字 (([*/+-])(\d+)) 的非匹配子组 ((?:...)*) 的“零次或多次重复”将匹配 所有次出现子表达式,但它似乎只匹配最后一个。
一方面,这是有道理的,因为正则表达式实际上只有三个匹配组,因此任何结果匹配只能有三个匹配。然而,“零次或多次重复”使它看起来好像遗漏了失败测试中的所有“中间”重复项(例如 1+2+3 中的 +2)。
// expected parse("1+2+3")=
// [][]string{[]string{"1+2+3", "1", "+", "2", "+", "3"}},
// got [][]string{[]string{"1+2+3", "1", "+", "3"}}
有没有办法使用 go 正则表达式解析这些类型的算术表达式,或者这是正则表达式(或 go/re2 正则表达式,或非/捕获组的一般组合)的基本限制?
(我意识到我可以按单词边界拆分并扫描标记以验证结构,但我对非/捕获组的这种限制比示例问题更感兴趣。)
【问题讨论】:
-
相关问题(swift,不去)stackoverflow.com/questions/37003623/…