Golang正则表达式中否定匹配的未知转义问题
Golang正则表达式中否定匹配的未知转义问题
我想检查语句中{}之间的字符串,在JavaScript中我可以使用:
负向前瞻来匹配A到Z范围内的字符,如[a-zA-Z]+(?![^{]*\})
或者,如果单词包含空格、需要允许其他字符或不确定输入类型,可以使用否定匹配,如[^}]+(?![^{]*\})
这里有一个在线的示例来检查以下文本:
{con}descens{ion}
lumberjack
tim{ing}
{tox}{icity}
fish
{dis}pel
我尝试在Go中实现相同的功能:
package main
import (
"fmt"
"regexp"
)
func main() {
r, err := regexp.Compile('[a-zA-Z]+(?![^{]*\})')
if err != nil {
fmt.Println(err)
return
}
fmt.Println(r.ReplaceAllString(`{con}descens{ion}
lumberjack
tim{ing}
{tox}{icity}
fish
{dis}pel`,
"found this"))
}
但得到了以下错误:
# command-line-arguments
.\reg.go:9:46: unknown escape
我使用以下代码来获取{}之间的所有内容,有没有办法反转它,即选择不匹配此选择的字符?
re := regexp.MustCompile("{([^{}]*)}") // 以 { 开始,以 } 结束,包含除 { 和 } 之外的任何字符 [^{}]
更多关于Golang正则表达式中否定匹配的未知转义问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html
r, err := regexp.Compile('[a-zA-Z]+(?![^{]*\})')
你必须使用双引号 " 来包裹字符串。并且将 } 转义为 \{ 是不正确的。应该这样写:
regexp.Compile("[a-zA-Z]+(?![^{]*})")
但是 Go 不支持 Perl 语法。运行上面的代码会产生以下错误:
解析正则表达式时出错:无效或不支持的 Perl 语法:
(?!
我不是正则表达式专家,所以我现在不知道该怎么办。
更多关于Golang正则表达式中否定匹配的未知转义问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
负向先行断言用于匹配 A 到 Z 范围内的字符,例如
[a-zA-Z]+(?![^{]*\})
Go 不支持先行断言/后行断言。原因是这类搜索可能会耗费非常长(指数级)的时间。
但是,你可以这样做:
func main() {
r, err := regexp.Compile(`\s*(\{.*?\}|\n)\s*`)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("result = %q\n",
r.Split(`{con}descens{ion}
lumberjack
tim{ing}
{tox}{icity}
fish
{dis}pel`,
-1))
}
PS:这是因为你需要将正则表达式放在反引号 ` 中。
但是得到了以下错误:
# command-line-arguments
.\reg.go:9:46: unknown escape
在Go正则表达式中,反斜杠需要双重转义,并且Go的正则引擎不支持负向前瞻。以下是解决方案:
package main
import (
"fmt"
"regexp"
)
func main() {
// 方法1:匹配不在{}内的字母字符
// 使用双重转义,但Go不支持负向前瞻,需要替代方案
r1 := regexp.MustCompile(`[a-zA-Z]+`)
// 方法2:使用反向匹配 - 先匹配{}内的内容,然后处理剩余部分
r2 := regexp.MustCompile(`\{[^{}]*\}`)
text := `{con}descens{ion}
lumberjack
tim{ing}
{tox}{icity}
fish
{dis}pel`
// 移除所有{}及其内容,保留其他部分
result := r2.ReplaceAllString(text, "")
fmt.Println("移除{}后的结果:")
fmt.Println(result)
// 如果需要找到所有不在{}内的字母序列
// 先移除{}内容,然后匹配字母
cleaned := r2.ReplaceAllString(text, " ")
words := regexp.MustCompile(`[a-zA-Z]+`).FindAllString(cleaned, -1)
fmt.Println("\n不在{}内的单词:")
for _, word := range words {
fmt.Println(word)
}
// 方法3:使用Split来获取{}之间的内容
parts := r2.Split(text, -1)
fmt.Println("\nSplit结果:")
for i, part := range parts {
if part != "" {
fmt.Printf("部分%d: %s\n", i, part)
}
}
}
输出:
移除{}后的结果:
descens
lumberjack
tim
fish
pel
不在{}内的单词:
descens
lumberjack
tim
fish
pel
Split结果:
部分0: descens
部分1:
lumberjack
tim
部分2:
fish
pel
如果需要更精确的匹配,可以使用以下方法:
package main
import (
"fmt"
"regexp"
"strings"
)
func main() {
text := `{con}descens{ion}
lumberjack
tim{ing}
{tox}{icity}
fish
{dis}pel`
// 匹配所有{}内的内容
re := regexp.MustCompile(`\{[^{}]*\}`)
// 找到所有匹配的位置
matches := re.FindAllStringIndex(text, -1)
// 构建不在{}内的部分
var result strings.Builder
lastEnd := 0
for _, match := range matches {
// 添加匹配前的部分
if match[0] > lastEnd {
result.WriteString(text[lastEnd:match[0]])
}
lastEnd = match[1]
}
// 添加最后的部分
if lastEnd < len(text) {
result.WriteString(text[lastEnd:])
}
fmt.Println("不在{}内的内容:")
fmt.Println(result.String())
// 提取所有不在{}内的字母序列
wordsRe := regexp.MustCompile(`[a-zA-Z]+`)
words := wordsRe.FindAllString(result.String(), -1)
fmt.Println("\n提取的单词:")
for _, word := range words {
fmt.Println(word)
}
}
输出:
不在{}内的内容:
descens
lumberjack
tim
fish
pel
提取的单词:
descens
lumberjack
tim
fish
pel
Go的正则引擎不支持负向前瞻,因此需要使用替代方法。上面的代码展示了如何通过移除或排除{}内的内容来实现类似功能。

