如何在 TCL 中严格使用正则表达式删除字符串中的重复字符?例如,我有一个这样的字符串aabbcddeffghh
,我只需要“ abcdefgh
”字符。我试过了lsort unique
,我能够得到独特的字符:
join [lsort -unique [split $mystring {}]]
但我regexp
只需要使用命令。
试试这个:
regsub -linestop -lineanchor -all {([a-z])\1+} $subject {\1} result
或者
regsub -linestop -nocase -lineanchor -all {([a-z])\1+} $subject {\1} result
解释
{
( # Match the regular expression below and capture its match into backreference number 1
[a-z] # Match a single character in the range between “a” and “z”
)
\1 # Match the same text as most recently matched by capturing group number 1
+ # Between one and unlimited times, as many times as possible, giving back as needed (greedy)
}
您不能仅使用 Tcl 的regsub
命令从字符串中删除所有不连续的双字符。它不支持访问前瞻序列中的反向引用,这意味着任何删除方案都必然会遇到重叠匹配区域的问题。
最简单的解决方法是包装在一个while
循环中(带有一个空的主体),使用regsub
将返回在给定一个变量来存储结果时执行的替换次数的事实(下面的最后一个参数):
set str "mississippi mud pie"
while {[regsub -all {(.)(.*)\1+} $str {\1\2} str]} {}
puts $str; # Prints "misp ude"
regsub -all {(.)(?=.*\1)} $subject {} result
它使用前瞻来检查是否有更多的角色实例。如果有,它会删除该字符。
您将始终保留最后一个字符。如果没有额外的库,就不可能在 TCL 中进行后视。
有关环视的更多信息:Regex 教程 - Lookahead and Lookbehind Zero-Width Assertions
编辑:嗯...似乎是 Tcl 8.5 中反向引用的错误。{(.).*\1}
匹配,但不匹配{(.)(?=.*\1)}
。它抱怨Invalid backreference number
. 如果没有前瞻中的反向引用,我看不到任何解决方案。
它可能只是我测试过的版本(ideone.com/pFS0Q)。我在网上找不到任何其他版本的 Tcl 解释器来测试。