3 回答
TA贡献1829条经验 获得超7个赞
这是另一个选项,它的正则表达式不那么复杂。它使用垃圾桶技巧。所以真正的数据在(第一和第二)捕获组上。
它甚至适用于像这样的嵌套引号:"a.'b.c'.d.e."f.g.h""
只要没有 2 级或更多级别的递归(如此处:"a.'b."c.d"'"
,引号内引号内引号)。
正则表达式是这样的:^"|['"](\w+(?:\.\w+)*)['"]|(\w+)
和代码:
package main
import (
"regexp"
"fmt"
)
func main() {
var re = regexp.MustCompile(`^"|['"](\w+(?:\.\w+)*)['"]|(\w+)`)
var str = `"a.'b.c'.d.e."f.g.h""`
result := re.FindAllStringSubmatch(str, -1)
for _, m := range result {
if (m[1] != "" || m[2] != "") {
fmt.Print(m[1] + m[2] + "\n")
}
}
}
输入:
"a.'b.c'.d.e."f.g.h""
输出:
a
b.c
d
e
f.g.h
TA贡献1780条经验 获得超3个赞
匹配平衡定界符对于正则表达式来说是一个复杂的问题,除非你使用类似Go pcre package 的东西。
相反,可以修改Go CSV 解析器。将其配置为用作.
分隔符、惰性引号(CSV 引号为'
)和可变长度记录。
package main
import (
"encoding/csv"
"fmt"
"io"
"log"
"strings"
)
func main() {
lines := `a.b.c.d
a.\"b.c\".d
a.'b.c'.d
`
csv := csv.NewReader(strings.NewReader(lines))
csv.Comma = '.'
csv.LazyQuotes = true
csv.FieldsPerRecord = -1
for {
record, err := csv.Read()
if err == io.EOF {
break
}
if err != nil {
log.Fatal(err)
}
fmt.Printf("%#v\n", record)
}
}
TA贡献1859条经验 获得超6个赞
由于 go 不支持否定前瞻,我认为找到与.
您要拆分的正则表达式相匹配的正则表达式并不容易/可能。相反,您可以匹配周围的文本并仅适当地捕获:
所以正则表达式本身有点难看,但这是细分(忽略转义字符):
(\'[^.'"]+(?:\.[^.'"]+)+\')|(\"[^.'"]+(?:\.[^.'"]+)+\")|(?:([^.'"]+)\.?)|(?:\.([^.'\"]+))
此正则表达式匹配四种情况,并捕获这些匹配的某些子集:
(\'[^.'"]+(?:\.[^.'"]+)+\')
- 匹配和捕获单引号文本\'
-'
逐字匹配[^.'"]+
- 匹配非行号和非句点的序列(?:\.[^.'"]+)+
- 匹配句点后跟一系列非引号和非句点,根据需要重复多次。没有被捕获。\'
-'
逐字匹配(\"[^.'"]+(?:\.[^.'"]+)+\")
- 匹配和捕获双引号文本与上面相同,但带有双引号
(?:([^.'"]+)\.?)
- 匹配由可选 开始的文本.
,不捕获.
([^.'"]+)
- 匹配和捕获非报价和非句点的序列\.?
- 可选择匹配一个句点(可选择捕获最后一位分隔文本)(?:\.([^.'"]+))
- 匹配前面有 a 的文本.
,不捕获.
与上面相同,但句点在捕获组之前,也是非可选的
转储捕获的示例代码:
package main
import (
"fmt"
"regexp"
)
func main() {
re := regexp.MustCompile("('[^.'\"]+(?:\\.[^.'\"]+)+')|(\"[^.'\"]+(?:\\.[^.'\"]+)+\")|(?:([^.'\"]+)\\.?)|(?:\\.([^.'\"]+))")
txt := "a.b.c.'d.e'"
result:= re.FindAllStringSubmatch(txt, -1)
for k, v := range result {
fmt.Printf("%d. %s\n", k, v)
}
}
- 3 回答
- 0 关注
- 119 浏览
添加回答
举报