求助:TCL 8.3中如何让正则仅匹配列表内的完整单词
解决方案:精确匹配列表中的完整单词(TCL 8.3兼容)
核心思路
既然输入本身是空格分隔的单词列表,直接将其作为TCL列表遍历比对,完全规避正则表达式的部分匹配问题,且完美兼容TCL 8.3版本。
修改后的代码
set text "Gi Gi Gi Tw Tw Tw Tw Tw Tw Tw Tw Tw Tw Twe Twe Gi Gi Te Te Te Te" set things2searchfor "Gi Te Tw Twe" foreach entry $things2searchfor { set count 0 set matches "" # 遍历text中的每个单词元素 foreach word $text { # 使用string equal做精确字符串匹配(TCL 8.3兼容) if {[string equal $word $entry]} { incr count append matches "$word " } } # 移除末尾多余空格 set matches [string trimright $matches] puts "There are $count matches found for $entry and they all are: $matches" }
代码说明
- 无需依赖正则表达式,直接利用TCL的列表特性处理空格分隔的文本,逐个比对单词与目标字符串的完全相等性,彻底避免
Tw匹配Twe这类部分匹配问题。 - 运行后将输出正确计数:Tw的匹配数为10,Twe为2,Gi为5,Te为4。
备选正则方案(若坚持用regexp)
如果一定要使用regexp,可以构建包含前后边界的正则表达式,适配TCL 8.3的语法:
set text "Gi Gi Gi Tw Tw Tw Tw Tw Tw Tw Tw Tw Tw Twe Twe Gi Gi Te Te Te Te" set things2searchfor "Gi Te Tw Twe" foreach entry $things2searchfor { # 构建匹配规则:要么在文本开头,要么前面是空格;要么在文本结尾,要么后面是空格 set pattern "(?:^| )$entry(?: |$)" # 使用-nocase可忽略大小写,按需添加 set allregexmatches [regexp -all -inline -nocase -- $pattern $text] # 由于每个匹配会包含前后空格,需要提取中间的目标单词 set filtered_matches "" foreach match $allregexmatches { append filtered_matches "[string trim $match] " } set filtered_matches [string trimright $filtered_matches] set numbrofmatches [llength [split $filtered_matches]] puts "There are $numbrofmatches matches found for $entry and they all are: $filtered_matches" }
该正则通过非捕获组匹配单词前后的空格或文本首尾,确保仅匹配完整单词,再通过string trim去除匹配结果中的空格,得到纯净的匹配列表。
内容的提问来源于stack exchange,提问作者Mario Jost
相关产品推荐
相关产品推荐

