如何在Go语言中按指定前缀和后缀分割字符串?
问题:正则表达式分割字符串不符合预期
我有一段十六进制格式的长字符串:
13242222160a06032c06cf00ca5c160bdc70102dfe0a12bc00a3b101000000cd01d60d0a13242222160a06032c0ccf00ca5bf10bdc74d029d05401fe0a12bc00a3b101000000d1e4270d0a1324222160a06032c1e0a12bc00a3b101000000d233ed0d0a
需要将它分割为数组,每个元素以1324作为前缀、0d0a作为后缀,预期得到3个元素:
arr[0] = 13242222160a06032c06cf00ca5c160bdc70102dfe0a12bc00a3b101000000cd01d60d0a
arr[1] = 13242222160a06032c0ccf00ca5bf10bdc74d029d05401fe0a12bc00a3b101000000d1e4270d0a
arr[2] = 1324222160a06032c1e0a12bc00a3b101000000d233ed0d0a
我写了如下Go代码,但运行后只输出整个原始字符串,显然正则表达式有问题:
package main import ( "fmt" "regexp" ) func main() { var testData = "13242222160a06032c06cf00ca5c160bdc70102dfe0a12bc00a3b101000000cd01d60d0a13242222160a06032c0ccf00ca5bf10bdc74d029d05401fe0a12bc00a3b101000000d1e4270d0a1324222160a06032c1e0a12bc00a3b101000000d233ed0d0a" re := regexp.MustCompile("^1324[0-9a-zA-Z]*0d0a") matches := re.FindAllString(testData, -1) for _, m := range matches { fmt.Printf("%s\n", m) } }
请问正确的正则表达式应该怎么写?
解决方案
原正则有两个核心问题:
^锚定了字符串的开头,导致正则只会从整个字符串的起始位置开始匹配,无法匹配后续以1324开头的片段;[0-9a-zA-Z]*是贪婪匹配,会尽可能匹配最长的符合规则的内容,所以会从第一个1324一直匹配到最后一个0d0a,直接把整个字符串当成一个匹配结果。
正确的正则表达式应该改成:
1324[0-9a-fA-F]*?0d0a
或者更精准的写法(匹配任意十六进制字符):
1324\p{XDigit}*?0d0a
正则说明:
- 去掉
^,允许正则在字符串任意位置匹配以1324开头的片段; - 将贪婪的
*改成非贪婪的*?,让正则匹配到第一个0d0a就停止,而不是一直匹配到最后一个; - 用
[0-9a-fA-F]或\p{XDigit}限定匹配十六进制字符,比[0-9a-zA-Z]更精准,避免匹配到非十六进制字符。
修改后的代码:
package main import ( "fmt" "regexp" ) func main() { var testData = "13242222160a06032c06cf00ca5c160bdc70102dfe0a12bc00a3b101000000cd01d60d0a13242222160a06032c0ccf00ca5bf10bdc74d029d05401fe0a12bc00a3b101000000d1e4270d0a1324222160a06032c1e0a12bc00a3b101000000d233ed0d0a" // 使用非贪婪匹配的正则 re := regexp.MustCompile("1324[0-9a-fA-F]*?0d0a") matches := re.FindAllString(testData, -1) for _, m := range matches { fmt.Printf("%s\n", m) } }
运行这段代码后,就能得到预期的3个元素。
内容的提问来源于stack exchange,提问作者anta40
相关产品推荐
相关产品推荐

