首次提交:初始化项目代码
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
1、app.log的测试文本内容2026年6月12日,邮箱:demo@miaoall.cn
|
||||
2、app.log的测试文本内容2026年6月12日,备用邮箱:admin@miaoall.cn
|
||||
@@ -0,0 +1,18 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// 全局仅编译一次,全局复用,性能最优
|
||||
//var pattern = `^1[3-9]\d{9}$`
|
||||
|
||||
// 更为严格的匹配
|
||||
var pattern = `^1(3[0-9]|4[5-9]|5[0-35-9]|6[2567]|7[0-9]|8[0-9]|9[0-35-9])[0-9]{8}$`
|
||||
var phoneRegex = regexp.MustCompile(pattern)
|
||||
|
||||
func main() {
|
||||
fmt.Println("合法手机号校验:", phoneRegex.MatchString("13812345678"))
|
||||
fmt.Println("非法手机号校验:", phoneRegex.MatchString("11111122222"))
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 测试场景1
|
||||
text1 := "余额200,积分50,代金券80"
|
||||
// 测试场景2:两个50,一个积分、一个代金券
|
||||
text2 := "余额200,积分50,代金券50"
|
||||
|
||||
fmt.Println("场景1结果:", filterNotScoreNum(text1))
|
||||
fmt.Println("场景2结果:", filterNotScoreNum(text2))
|
||||
}
|
||||
|
||||
// filterNotScoreNum 过滤:数字前面紧邻是“积分”的数字剔除,等价 (?!积分) 反向语义
|
||||
func filterNotScoreNum(text string) []string {
|
||||
numRe := regexp.MustCompile(`\d+`)
|
||||
indexList := numRe.FindAllStringIndex(text, -1)
|
||||
var validNums []string
|
||||
|
||||
for _, pos := range indexList {
|
||||
startIdx, endIdx := pos[0], pos[1]
|
||||
numStr := text[startIdx:endIdx]
|
||||
|
||||
// 读取数字前面的上下文,倒推判断前面是不是“积分”
|
||||
// 从数字开头位置向前读取2个汉字的符文长度
|
||||
beforeStr := text[:startIdx]
|
||||
// 倒着解码两个rune
|
||||
runeCnt := 0
|
||||
var lastTwoRunes []rune
|
||||
// 反向遍历符文
|
||||
for i := len(beforeStr); i > 0 && runeCnt < 2; {
|
||||
r, size := utf8.DecodeLastRuneInString(beforeStr[:i])
|
||||
lastTwoRunes = append([]rune{r}, lastTwoRunes...)
|
||||
i -= size
|
||||
runeCnt++
|
||||
}
|
||||
|
||||
// 判断数字前两个汉字是否为“积分”
|
||||
isScoreNum := false
|
||||
if len(lastTwoRunes) == 2 {
|
||||
prefix := string(lastTwoRunes)
|
||||
if prefix == "积分" {
|
||||
isScoreNum = true
|
||||
}
|
||||
}
|
||||
|
||||
// 不是积分对应的数字才保留
|
||||
if !isScoreNum {
|
||||
validNums = append(validNums, numStr)
|
||||
}
|
||||
}
|
||||
return validNums
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// checkDigitSuffix 等价原 \d+(?!\D+$)
|
||||
// 入参:完整字符串、一段数字的结束下标
|
||||
// 返回:true = 符合条件(数字后面不全是字母)
|
||||
func checkDigitSuffix(s string, digitEnd int) bool {
|
||||
// 数字后面无任何字符,直接不符合
|
||||
if digitEnd >= len(s) {
|
||||
return false
|
||||
}
|
||||
after := s[digitEnd:]
|
||||
// 遍历数字之后所有字符
|
||||
allLetter := true
|
||||
for _, r := range after {
|
||||
// 判断是否大小写字母
|
||||
if !unicode.IsLetter(r) {
|
||||
allLetter = false
|
||||
break
|
||||
}
|
||||
}
|
||||
// 不全是字母 → 返回true匹配
|
||||
return !allLetter
|
||||
}
|
||||
|
||||
func main() {
|
||||
pwdList := []string{"abc123", "123abc", "abcdef", "x99!yy", "789#"}
|
||||
digitRe := regexp.MustCompile(`\d+`)
|
||||
|
||||
fmt.Println("密码\t匹配结果")
|
||||
fmt.Println("----------------")
|
||||
for _, pwd := range pwdList {
|
||||
// 找出所有数字段
|
||||
allDigitIdx := digitRe.FindAllStringIndex(pwd, -1)
|
||||
matchFlag := false
|
||||
|
||||
for _, idx := range allDigitIdx {
|
||||
endPos := idx[1]
|
||||
if checkDigitSuffix(pwd, endPos) {
|
||||
matchFlag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("%s\t%t\n", pwd, matchFlag)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 场景1:Longest 长短匹配对比(最核心模式切换)
|
||||
fmt.Println("===== 1. Longest最长匹配 vs 默认first匹配 =====")
|
||||
expr := `(a+)|(aaa)`
|
||||
// 默认 leftmost-first
|
||||
reDefault := regexp.MustCompile(expr)
|
||||
fmt.Println("默认模式匹配aaaa:", reDefault.FindString("aaaa")) // 优先第一个分支a+,短匹配
|
||||
|
||||
// 开启最长匹配
|
||||
reLong := regexp.MustCompile(expr)
|
||||
reLong.Longest()
|
||||
fmt.Println("Longest最长模式匹配aaaa:", reLong.FindString("aaaa"))
|
||||
|
||||
// 场景2:. 匹配换行 RE2专属 (?s:.)
|
||||
fmt.Println("\n===== 2. 点号匹配换行符 =====")
|
||||
strWithLine := "hello\nworld"
|
||||
// 普通. 不跨换行
|
||||
reDotNormal := regexp.MustCompile(`hello.world`)
|
||||
fmt.Println("普通.匹配换行:", reDotNormal.MatchString(strWithLine))
|
||||
// (?s:.) 让.识别换行
|
||||
reDotAll := regexp.MustCompile(`(?s:hello.world)`)
|
||||
fmt.Println("(?s:.)开启跨行匹配:", reDotAll.MatchString(strWithLine))
|
||||
|
||||
// 场景3:大小写不敏感匹配(无修饰符,字符组兼容大小写)
|
||||
fmt.Println("\n===== 3. 大小写忽略匹配方案 =====")
|
||||
target := "Apple APPLE apple aPpLe"
|
||||
// 写法1:字符组罗列大小写
|
||||
reCase := regexp.MustCompile(`[Aa][Pp][Pp][Ll][Ee]`)
|
||||
fmt.Println("大小写全部匹配结果:", reCase.FindAllString(target, -1))
|
||||
|
||||
// 场景4:CompilePOSIX 天生Longest语义
|
||||
fmt.Println("\n===== 4. CompilePOSIX 原生最长匹配 =====")
|
||||
rePosix, _ := regexp.CompilePOSIX(expr)
|
||||
fmt.Println("CompilePOSIX匹配aaaa:", rePosix.FindString("aaaa"))
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// 通用邮箱正则
|
||||
var emailRegex = regexp.MustCompile(`[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}`)
|
||||
|
||||
func main() {
|
||||
// 测试文本:复用文档本地测试域名,零外网依赖
|
||||
content := "工作邮箱:demo@miaoall.cn,备用邮箱:admin@miaoall.cn,网站地址:https://www.miaoall.cn"
|
||||
contentBytes := []byte(content) // 字节流数据,适配[]byte系列API
|
||||
|
||||
fmt.Println("========== 1. 基础匹配校验API ==========")
|
||||
// 字符串匹配校验
|
||||
fmt.Println("字符串是否含邮箱(MatchString):", emailRegex.MatchString(content))
|
||||
// 字节流匹配校验
|
||||
fmt.Println("字节流是否含邮箱(Match):", emailRegex.Match(contentBytes))
|
||||
|
||||
fmt.Println("\n========== 2. 单次匹配内容/下标API ==========")
|
||||
// 单次字符串匹配内容
|
||||
firstEmail := emailRegex.FindString(content)
|
||||
fmt.Println("首个匹配邮箱(FindString):", firstEmail)
|
||||
// 单次字符串匹配下标
|
||||
firstIndex := emailRegex.FindStringIndex(content)
|
||||
fmt.Println("首个邮箱起止下标(FindStringIndex):", firstIndex)
|
||||
// 单次字节流匹配内容、下标
|
||||
firstByteEmail := emailRegex.Find(contentBytes)
|
||||
fmt.Println("字节流首个邮箱(Find):", string(firstByteEmail))
|
||||
firstByteIndex := emailRegex.FindIndex(contentBytes)
|
||||
fmt.Println("字节流首个邮箱下标(FindIndex):", firstByteIndex)
|
||||
|
||||
fmt.Println("\n========== 3. 批量匹配内容/下标API ==========")
|
||||
// 批量匹配所有字符串结果
|
||||
allEmail := emailRegex.FindAllString(content, -1)
|
||||
fmt.Println("全部邮箱(FindAllString):", allEmail)
|
||||
// 批量匹配所有下标
|
||||
allIndex := emailRegex.FindAllStringIndex(content, -1)
|
||||
fmt.Println("全部邮箱下标(FindAllStringIndex):", allIndex)
|
||||
// 字节流批量匹配
|
||||
allByteEmail := emailRegex.FindAll(contentBytes, -1)
|
||||
fmt.Print("字节流全部邮箱(FindAll):")
|
||||
for _, v := range allByteEmail {
|
||||
fmt.Print(string(v), " ")
|
||||
}
|
||||
fmt.Println()
|
||||
|
||||
fmt.Println("\n========== 4. 基础捕获组匹配API ==========")
|
||||
// 复用链接正则,测试子匹配
|
||||
var urlRegex = regexp.MustCompile(`(?:http|https)://(\w+\.\w+\.\w+)`)
|
||||
// 单次字符串子匹配
|
||||
subMatch := urlRegex.FindStringSubmatch(content)
|
||||
fmt.Println("单次子匹配结果(FindStringSubmatch):", subMatch)
|
||||
// 单次子匹配下标
|
||||
subMatchIndex := urlRegex.FindStringSubmatchIndex(content)
|
||||
fmt.Println("单次子匹配下标(FindStringSubmatchIndex):", subMatchIndex)
|
||||
// 批量子匹配、下标
|
||||
allSubMatch := urlRegex.FindAllStringSubmatch(content, -1)
|
||||
fmt.Println("批量子匹配(FindAllStringSubmatch):", allSubMatch)
|
||||
allSubIndex := urlRegex.FindAllStringSubmatchIndex(content, -1)
|
||||
fmt.Println("批量子匹配下标(FindAllStringSubmatchIndex):", allSubIndex)
|
||||
|
||||
fmt.Println("\n========== 5. 文本分割API ==========")
|
||||
// 按邮箱分割原文本
|
||||
splitRes := emailRegex.Split(content, -1)
|
||||
fmt.Println("正则分割文本结果(Split):", splitRes)
|
||||
|
||||
fmt.Println("\n========== 6. 流式读取API(防OOM) ==========")
|
||||
// 流式读取适配超大文件,逐符文读取,杜绝全量加载内存溢出
|
||||
file, err := os.Open("regexp/app.log")
|
||||
if err != nil {
|
||||
fmt.Println("流式文件读取模拟(无文件则跳过):", err)
|
||||
} else {
|
||||
defer file.Close()
|
||||
// bufio.Reader 实现 io.RuneReader 接口,可用于所有流式正则API
|
||||
reader := bufio.NewReader(file)
|
||||
fmt.Println("流式匹配是否含邮箱(MatchReader):", emailRegex.MatchReader(reader))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
var userRegex = regexp.MustCompile(`姓名:([\p{Han}a-zA-Z0-9]+),年龄:(\d+),电话:(\d{11})`)
|
||||
|
||||
func main() {
|
||||
text := "用户信息:姓名:孙三苗,年龄:20,电话:11112345678" // 号码不存在仅供测试
|
||||
match := userRegex.FindStringSubmatch(text)
|
||||
if len(match) > 0 {
|
||||
fmt.Println("完整匹配:", match[0])
|
||||
fmt.Println("姓名:", match[1])
|
||||
fmt.Println("年龄:", match[2])
|
||||
fmt.Println("电话:", match[3])
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
var namedRegex = regexp.MustCompile(`姓名:(?P<name>[\p{Han}a-zA-Z0-9]+),城市:(?P<city>[\p{Han}a-zA-Z0-9]+)`)
|
||||
|
||||
func main() {
|
||||
text := "姓名:孙三苗,城市:北京"
|
||||
match := namedRegex.FindStringSubmatch(text)
|
||||
for i, name := range namedRegex.SubexpNames() {
|
||||
if i > 0 && name != "" {
|
||||
fmt.Printf("%s:%s\n", name, match[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// 匹配 http/https 协议链接,不单独捕获协议字段
|
||||
var urlRegex = regexp.MustCompile(`(?:http|https)://\w+\.\w+\.\w+`)
|
||||
|
||||
func main() {
|
||||
text := "站点:https://www.miaoall.cn 镜像:http://www.miaoall.cn"
|
||||
res := urlRegex.FindAllString(text, -1)
|
||||
fmt.Println("匹配链接:", res)
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 1、字符串反向引用脱敏 ReplaceAllString
|
||||
mobileRe := regexp.MustCompile(`(\d{3})\d{4}(\d{4})`)
|
||||
phone := "12311111111"
|
||||
// $$ 转义输出单个字面$
|
||||
res1 := mobileRe.ReplaceAllString(phone, "前缀$$ $1****$2 后缀")
|
||||
fmt.Println("1.ReplaceAllString 手机号脱敏+$转义:", res1)
|
||||
|
||||
// 命名捕获组搭配${name}格式
|
||||
nameRe := regexp.MustCompile(`姓名:(?P<name>[\p{Han}]+)`)
|
||||
userText := "姓名:王五"
|
||||
resName := nameRe.ReplaceAllString(userText, "用户${name}已登记")
|
||||
fmt.Println("命名捕获组替换:", resName)
|
||||
|
||||
// 2、字面量&常规替换核心对比(带捕获组,差异肉眼可见)
|
||||
litStr := "价格$100,优惠$20"
|
||||
numRe := regexp.MustCompile(`(\d+)`)
|
||||
res2Normal := numRe.ReplaceAllString(litStr, "数值$1")
|
||||
res2Lit := numRe.ReplaceAllLiteralString(litStr, "数值$1")
|
||||
fmt.Println("2.ReplaceAllString 解析捕获组$1:", res2Normal)
|
||||
fmt.Println("2.ReplaceAllLiteralString 纯字面$1:", res2Lit)
|
||||
|
||||
// 3、动态回调替换 ReplaceAllStringFunc
|
||||
priceText := "金额:10、20、50"
|
||||
res3 := numRe.ReplaceAllStringFunc(priceText, func(s string) string {
|
||||
val, _ := strconv.Atoi(s)
|
||||
return strconv.Itoa(val * 2)
|
||||
})
|
||||
fmt.Println("3.ReplaceAllStringFunc 数值翻倍:", res3)
|
||||
|
||||
// ---------------------- []byte 字节系列替换API ----------------------
|
||||
bytePhone := []byte("12311111111")
|
||||
// 4.ReplaceAll 字节版反向引用
|
||||
resByte1 := mobileRe.ReplaceAll(bytePhone, []byte("$1****$2"))
|
||||
fmt.Println("4.ReplaceAll 字节脱敏:", string(resByte1))
|
||||
|
||||
// 5.ReplaceAllLiteral 字节字面量演示
|
||||
byteSrc := []byte("积分30")
|
||||
resByte2 := numRe.ReplaceAllLiteral(byteSrc, []byte("分数$1"))
|
||||
fmt.Println("5.ReplaceAllLiteral 字节字面量:", string(resByte2))
|
||||
|
||||
// 6.ReplaceAllFunc 字节回调自定义逻辑
|
||||
bytePrice := []byte("标价5 标价15")
|
||||
resByte3 := numRe.ReplaceAllFunc(bytePrice, func(b []byte) []byte {
|
||||
val, _ := strconv.Atoi(string(b))
|
||||
return []byte(strconv.Itoa(val + 10))
|
||||
})
|
||||
fmt.Println("6.ReplaceAllFunc 字节数值加10:", string(resByte3))
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println("=== Golang正则表达式ReplaceAllLiteralString使用示例 ===")
|
||||
|
||||
// 1. 基本用法演示
|
||||
fmt.Println("\n1. 基本用法演示")
|
||||
text := "Hello world! This is a world of Go programming. Welcome to the world!"
|
||||
|
||||
// 使用普通替换
|
||||
normalReplace := regexp.MustCompile(`world`).ReplaceAllString(text, "universe")
|
||||
fmt.Printf("原始文本: %s\n", text)
|
||||
fmt.Printf("普通替换(ReplaceAllString): %s\n", normalReplace)
|
||||
|
||||
// 使用字面量替换
|
||||
literalReplace := regexp.MustCompile(`world`).ReplaceAllLiteralString(text, "universe")
|
||||
fmt.Printf("字面量替换(ReplaceAllLiteralString): %s\n", literalReplace)
|
||||
|
||||
// 2. 特殊字符处理对比
|
||||
fmt.Println("\n2. 特殊字符处理对比")
|
||||
specialText := "Price: $100, Discount: $20, Total: $80"
|
||||
|
||||
// 普通替换 - $有特殊含义
|
||||
normalResult := regexp.MustCompile(`\$`).ReplaceAllString(specialText, "USD ")
|
||||
fmt.Printf("特殊字符 - 普通替换: %s\n", normalResult)
|
||||
|
||||
// 字面量替换 - $被视为普通字符
|
||||
literalResult := regexp.MustCompile(`\$`).ReplaceAllLiteralString(specialText, "USD ")
|
||||
fmt.Printf("特殊字符 - 字面量替换: %s\n", literalResult)
|
||||
|
||||
// 3. 捕获组符号处理
|
||||
fmt.Println("\n3. 捕获组符号处理")
|
||||
groupText := "Pattern: (abc) and [def] with {ghi}"
|
||||
|
||||
// 普通替换 - $1, $2等会被当作捕获组引用
|
||||
normalGroup := regexp.MustCompile(`\(([^\)]+)\)`).ReplaceAllString(groupText, "GROUP($1)")
|
||||
fmt.Printf("捕获组 - 普通替换: %s\n", normalGroup)
|
||||
|
||||
// 字面量替换 - $符号被当作普通字符处理
|
||||
literalGroup := regexp.MustCompile(`\(([^\)]+)\)`).ReplaceAllLiteralString(groupText, "GROUP($1)")
|
||||
fmt.Printf("捕获组 - 字面量替换: %s\n", literalGroup)
|
||||
|
||||
// 4. 实际应用场景 - HTML转义
|
||||
fmt.Println("\n4. 实际应用场景 - HTML转义")
|
||||
htmlText := "<div class='test'>Click & go to \"page\"</div>"
|
||||
|
||||
// 正确的HTML转义方法 - 使用ReplaceAllStringFunc
|
||||
htmlReplacer := regexp.MustCompile(`[<>&"']`)
|
||||
escapedHTML := htmlReplacer.ReplaceAllStringFunc(htmlText, func(match string) string {
|
||||
switch match {
|
||||
case "<":
|
||||
return "<"
|
||||
case ">":
|
||||
return ">"
|
||||
case "&":
|
||||
return "&"
|
||||
case "\"":
|
||||
return """
|
||||
case "'":
|
||||
return "'"
|
||||
default:
|
||||
return match
|
||||
}
|
||||
})
|
||||
fmt.Printf("HTML转义前: %s\n", htmlText)
|
||||
fmt.Printf("HTML转义后: %s\n", escapedHTML)
|
||||
|
||||
// 5. SQL注入防护
|
||||
fmt.Println("\n5. SQL注入防护示例")
|
||||
sqlText := "SELECT * FROM users WHERE name = 'admin'; DROP TABLE users; --'"
|
||||
|
||||
// 移除危险字符 - 使用ReplaceAllLiteralString
|
||||
sqlSafe := regexp.MustCompile(`['";--]`).ReplaceAllLiteralString(sqlText, "_")
|
||||
fmt.Printf("原始SQL: %s\n", sqlText)
|
||||
fmt.Printf("净化后SQL: %s\n", sqlSafe)
|
||||
|
||||
// 6. 路径规范化
|
||||
fmt.Println("\n6. 路径规范化")
|
||||
pathText := "/home/user/../documents/./files//temp/"
|
||||
|
||||
// 标准化路径分隔符
|
||||
normalizedPath := regexp.MustCompile(`/+`).ReplaceAllLiteralString(pathText, "/")
|
||||
fmt.Printf("原始路径: %s\n", pathText)
|
||||
fmt.Printf("标准化路径: %s\n", normalizedPath)
|
||||
|
||||
// 7. 用户输入清理
|
||||
fmt.Println("\n7. 用户输入清理")
|
||||
userInput := "User input with <script>alert('xss')</script> and other dangerous content"
|
||||
|
||||
// 移除潜在危险标签
|
||||
cleanInput := regexp.MustCompile(`<script[^>]*>.*?</script>`).ReplaceAllLiteralString(userInput, "")
|
||||
fmt.Printf("原始输入: %s\n", userInput)
|
||||
fmt.Printf("清理后输入: %s\n", cleanInput)
|
||||
|
||||
// 8. 电话号码格式化
|
||||
fmt.Println("\n8. 电话号码格式化")
|
||||
phoneText := "Call me at 1234567890 or 0987654321 for more info"
|
||||
|
||||
// 正确的格式化方法 - 使用ReplaceAllString(因为需要捕获组引用)
|
||||
correctFormattedPhone := regexp.MustCompile(`(\d{3})(\d{3})(\d{4})`).ReplaceAllString(phoneText, "$1-$2-$3")
|
||||
fmt.Printf("原始号码: %s\n", phoneText)
|
||||
fmt.Printf("格式化号码: %s\n", correctFormattedPhone)
|
||||
|
||||
// 9. 敏感信息脱敏
|
||||
fmt.Println("\n9. 敏感信息脱敏")
|
||||
sensitiveText := "Email: john@example.com, Phone: 123-456-7890, SSN: 123-45-6789"
|
||||
|
||||
// 脱敏邮箱 - 使用ReplaceAllString(需要捕获组)
|
||||
emailMasked := regexp.MustCompile(`([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})`).ReplaceAllString(sensitiveText, "***@***.com")
|
||||
fmt.Printf("原始信息: %s\n", sensitiveText)
|
||||
fmt.Printf("邮箱脱敏: %s\n", emailMasked)
|
||||
|
||||
// 10. 关键词过滤
|
||||
fmt.Println("\n10. 关键词过滤")
|
||||
badWordsText := "This contains some bad words like crap, damn, and hell that should be filtered out"
|
||||
|
||||
// 过滤不良词汇
|
||||
filteredText := regexp.MustCompile(`(?i)(crap|damn|hell)`).ReplaceAllLiteralString(badWordsText, "***")
|
||||
fmt.Printf("原文本: %s\n", badWordsText)
|
||||
fmt.Printf("过滤后: %s\n", filteredText)
|
||||
|
||||
// 11. 价格格式化
|
||||
fmt.Println("\n11. 价格格式化")
|
||||
priceText := "Product A costs $29.99, Product B costs $199.99"
|
||||
|
||||
// 将美元符号替换为人民币符号 - 使用ReplaceAllLiteralString
|
||||
rmbPrice := regexp.MustCompile(`\$`).ReplaceAllLiteralString(priceText, "¥")
|
||||
fmt.Printf("原始价格: %s\n", priceText)
|
||||
fmt.Printf("人民币价格: %s\n", rmbPrice)
|
||||
|
||||
// 12. 批量替换示例
|
||||
fmt.Println("\n12. 批量替换示例")
|
||||
batchText := "Replace @user with [USERNAME] and #hashtag with [HASHTAG]"
|
||||
|
||||
// 替换多个模式
|
||||
result := batchText
|
||||
result = regexp.MustCompile(`@(\w+)`).ReplaceAllLiteralString(result, "[USER]")
|
||||
result = regexp.MustCompile(`#(\w+)`).ReplaceAllLiteralString(result, "[TAG]")
|
||||
fmt.Printf("原始文本: %s\n", batchText)
|
||||
fmt.Printf("批量替换后: %s\n", result)
|
||||
|
||||
// 13. 特殊字符处理
|
||||
fmt.Println("\n13. 特殊字符处理")
|
||||
specialCharsText := "This has special chars: $10, \\path, $variable, and \\n newlines"
|
||||
|
||||
// 处理包含$和\的文本 - 使用ReplaceAllLiteralString确保特殊字符被正确处理
|
||||
safeReplace := regexp.MustCompile(`special chars: \$10, \\path`).ReplaceAllLiteralString(specialCharsText, "SAFE TEXT")
|
||||
fmt.Printf("原始文本: %s\n", specialCharsText)
|
||||
fmt.Printf("安全替换后: %s\n", safeReplace)
|
||||
|
||||
// 14. 性能对比演示
|
||||
fmt.Println("\n14. 性能对比演示")
|
||||
longText := strings.Repeat("This is a test string with pattern to replace. ", 1000)
|
||||
|
||||
// 测试ReplaceAllLiteralString性能
|
||||
re1 := regexp.MustCompile(`pattern`)
|
||||
|
||||
// 由于无法直接测试性能,这里展示用法
|
||||
literalResult = re1.ReplaceAllLiteralString(longText, "replacement")
|
||||
fmt.Printf("ReplaceAllLiteralString处理长文本完成,结果长度: %d\n", len(literalResult))
|
||||
|
||||
// 15. 实际应用:日志清理
|
||||
fmt.Println("\n15. 实际应用:日志清理")
|
||||
logText := "INFO: User login success for admin@company.com at 2026-06-15 10:30:45"
|
||||
|
||||
// 清理敏感信息
|
||||
cleanLog := regexp.MustCompile(`\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b`).ReplaceAllLiteralString(logText, "[EMAIL_REDACTED]")
|
||||
fmt.Printf("原始日志: %s\n", logText)
|
||||
fmt.Printf("清理后日志: %s\n", cleanLog)
|
||||
|
||||
fmt.Println("\n=== ReplaceAllLiteralString vs ReplaceAllString 对比 ===")
|
||||
fmt.Println("ReplaceAllString: 替换字符串中的$符号有特殊含义,用于引用捕获组")
|
||||
fmt.Println("ReplaceAllLiteralString: 替换字符串中的$符号被当作普通字符处理,不会被解释为捕获组引用")
|
||||
fmt.Println("使用场景: 当替换字符串包含$、\\等特殊字符且不想被解释时,使用ReplaceAllLiteralString")
|
||||
fmt.Println("\n注意: 如果需要使用捕获组功能,应使用ReplaceAllString或ReplaceAllStringFunc")
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
html := "<div>内容1</div><div>内容2</div>"
|
||||
// 贪婪匹配会一次性匹配到最后闭合标签,导致合并结果
|
||||
greedy := regexp.MustCompile(`<div>(.*)</div>`)
|
||||
fmt.Println("贪婪匹配错误结果:", greedy.FindAllString(html, -1))
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
html := "<div>内容1</div><div>内容2</div>"
|
||||
lazy := regexp.MustCompile(`<div>(.*?)</div>`)
|
||||
fmt.Println("非贪婪匹配正确结果:", lazy.FindAllString(html, -1))
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
text := "A:99元,B:199元,积分:50"
|
||||
// 捕获【数字+元】整体,分组单独取出数字
|
||||
re := regexp.MustCompile(`(\d+)元`)
|
||||
matches := re.FindAllStringSubmatch(text, -1)
|
||||
|
||||
var amountList []string
|
||||
for _, item := range matches {
|
||||
// item[0] = 99元,item[1] = 99 纯数字
|
||||
amountList = append(amountList, item[1])
|
||||
}
|
||||
fmt.Println("仅提取金额数字:", amountList)
|
||||
}
|
||||
Reference in New Issue
Block a user