Tcl regexp元素提取异常:为何结果与预期不符?
问题原因分析
你遇到的问题核心在于Tcl中regexp -all -inline命令的捕获组返回规则:
当正则表达式包含捕获组(比如你用的(\S+))时,-inline选项会把整个匹配结果和每个捕获组的匹配内容都依次加入返回列表里。
举个具体例子,当你的正则匹配到第一个a时:
- 整个匹配的内容是
a - 捕获组
(\S+)捕获的内容也是a
所以这一次匹配就会向结果列表里添加两个a;同理每个b也会被重复添加一次,最终就出现了你看到的a a b b a a b b b b a a这种重复的结果。
而你的原始字符串里实际的非空白字符序列是a、b、a、b、b、a,每个都是单独的非空白字符,每次匹配\S+都会匹配单个字符,再加上捕获组的重复输出,就导致了结果翻倍。
解决办法
有几种方式可以得到你预期的结果:
1. 使用非捕获组
把正则里的捕获组改成非捕获组(?:\S+),这样regexp就只会返回整个匹配的内容,不会额外输出捕获组的结果:
set x "\ \ a\ b\ \ a\ b\ b\ a\ \ \ " set match [regexp -all -inline {(?:\S+)} $x] # 此时match的结果就是 {a b a b b a}
2. 去掉捕获组,直接匹配非空白字符序列
如果不需要捕获组的功能,直接用\S+即可,效果和非捕获组完全一致:
set match [regexp -all -inline {\S+} $x]
3. 过滤结果列表,只保留捕获组的内容
如果你因为某些原因必须保留捕获组,可以对返回的列表进行过滤,只取捕获组对应的元素(列表结构是[整个匹配1, 捕获组1, 整个匹配2, 捕获组2,...],所以取索引为奇数的元素即可):
set match [regexp -all -inline {(\S+)} $x] set expected [lrange $match 1 end 2] # expected的结果就是 {a b a b b a}
内容的提问来源于stack exchange,提问作者user3512999
相关产品推荐
相关产品推荐

