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

3 回复
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))
}

Playground

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的正则引擎不支持负向前瞻,因此需要使用替代方法。上面的代码展示了如何通过移除或排除{}内的内容来实现类似功能。

回到顶部