如何在Go中通过正则表达式在下面分割输入字符串?字符串示例:
我知道如何按点分隔,但是如何避免用引号分隔?
"a.b.c.d" -> ["a", "b", "c", "d"]
"a."b.c".d" -> ["a", "b.c", "d"]
"a.'b.c'.d" -> ["a", "b.c", "d"]
答案 0 :(得分:1)
由于go不支持负面的前瞻性,因此我认为找到匹配要分割的.
的正则表达式并不容易。相反,您可以匹配周围的文本并仅适当捕获:
所以正则表达式本身有点丑陋,但这是细分(忽略go的转义字符):
(\'[^.'"]+(?:\.[^.'"]+)+\')|(\"[^.'"]+(?:\.[^.'"]+)+\")|(?:([^.'"]+)\.?)|(?:\.([^.'\"]+))
此正则表达式匹配四种情况,并捕获这些匹配的某些子集:
(\'[^.'"]+(?:\.[^.'"]+)+\')
-匹配并捕获单引号文字
\'
-从字面上匹配'
[^.'"]+
-非引号和非句点的匹配顺序(?:\.[^.'"]+)+
-匹配一个句点,然后是一系列非引号和非句点,并根据需要重复多次。未捕获。\'
-从字面上匹配'
(\"[^.'"]+(?:\.[^.'"]+)+\")
-匹配并捕获双引号文字
(?:([^.'"]+)\.?)
-用可选的.
开头的匹配文本,而不捕获.
([^.'"]+)
-匹配和捕获非引号和非句点的顺序\.?
-(可选)匹配一个句点(用于捕获定界文本的最后一位)(?:\.([^.'"]+))
-匹配以.
开头的文本,但不捕获.
转储捕获的示例代码:
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)
}
}
答案 1 :(得分:1)
匹配正则表达式是一个复杂的问题,John's answer证明了这一点。除非您使用的是Go pcre package之类的东西。
可以改编Go CSV parser。配置它以使用.
作为分隔符,惰性引号(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)
}
}
答案 2 :(得分:1)
这是另一种选项,它的正则表达式稍微有些黑。它使用trash bin trick。因此,实际数据位于(第一个和第二个)捕获组上。
它甚至适用于嵌套引号:ng build --prod
,只要不存在2或更高级别的递归即可(如此处:"a.'b.c'.d.e."f.g.h""
,引号内的引号在引号内)。
正则表达式是:"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""