如何修改Golang regexp实现CV(N)(C)结构字符串的正确音节分割?
修正正则实现CV(N)(C)结构的音节正确分割
问题根源
原正则[ptk][aeiou][mn]?[ptk]?采用贪婪匹配逻辑,当字符串包含多个音节时,会把属于下一个音节的起始辅音(C)当作当前音节的可选结尾C消耗掉,导致后续字符无法匹配成完整音节。比如tanpa中,原正则会匹配tanp(把pa的p当作tan的可选结尾C),而非预期的tan+pa。
解决方案
通过正向否定预查限制结尾可选C的匹配条件:确保该C后面不是另一个音节的起始(即不跟着C+V),避免抢占下一个音节的起始辅音。
调整后的正则表达式结构为:
(CV(?:N)?(?:C(?!CV))?)
其中:
CV(?:N)?:匹配基础的CV或CVN结构(?:C(?!CV))?:可选匹配结尾C,但通过(?!CV)确保这个C后面没有新的C+V音节起始,避免贪婪消耗下一个音节的C。
修改后的代码
package main import ( "fmt" "regexp" "strings" ) func main() { words := []string{"ta", "tan", "tank", "tapa", "tanpa", "tankpa", "tapam", "tanpam", "tankpam", "tapamt", "tanpamt", "tankpamt", "tapitetot"} expected := []string{"ta", "tan", "tank", "ta.pa", "tan.pa", "tank.pa", "ta.pam", "tan.pam", "tank.pam", "ta.pamt", "tan.pamt", "tank.pamt", "ta.pi.te.tot"} C := "[ptk]" V := "[aeiou]" N := "[mn]" // 调整正则,加入正向否定预查限制结尾C的匹配 cvnc := regexp.MustCompile(fmt.Sprintf("(%s%s%s?(?:%s(?!%s%s))?)", C, V, N, C, C, V)) for i := range words { fmt.Println(words[i], "\n expect", strings.Split(expected[i], "."), "\n got ", cvnc.FindAllString(words[i], -1)) } }
验证结果
修改后运行代码,所有案例均可得到预期的分割结果:
tanpa→["tan", "pa"]tapitetot→["ta", "pi", "te", "tot"]- 其他单音节或多音节案例均符合预期输出。
内容的提问来源于stack exchange,提问作者bigyihsuan
相关产品推荐
相关产品推荐

