如何在TCL中严格使用regexp删除字符串中的重复字符?
例如,我有一个像aabbcddeffghh
这样的字符串,我只需要“abcdefgh
”字符。我尝试使用lsort unique
,我可以获得独特的字符:
join [lsort -unique [split $mystring {}]]
但我只需要使用regexp
命令。
答案 0 :(得分:3)
试试这个:
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)
}
答案 1 :(得分:3)
您不能仅使用Tcl的regsub
命令从字符串中删除所有非连续的双字符。它不支持在先行序列中访问反向引用,这意味着任何删除方案都必然会遇到重叠匹配区域的问题。
最简单的解决方法是使用while
将返回在给定变量以存储结果时执行的替换次数的事实来换行regsub
循环(使用空体) (下面的最后一个论点):
set str "mississippi mud pie"
while {[regsub -all {(.)(.*)\1+} $str {\1\2} str]} {}
puts $str; # Prints "misp ude"
答案 2 :(得分:1)
regsub -all {(.)(?=.*\1)} $subject {} result
它使用前瞻来检查是否还有该角色的实例。如果有,则删除该字符。
您将始终保留最后一个角色。如果没有额外的库,就无法在TCL中进行后视。
有关环顾四周的更多信息:Regex tutorial - Lookahead and Lookbehind Zero-Width Assertions
编辑:嗯......似乎是Tcl 8.5中反向引用的错误。 {(.).*\1}
匹配,但不匹配{(.)(?=.*\1)}
。它抱怨Invalid backreference number
。如果没有在预测中进行反向引用,我无法看到任何解决方案。
它可能只是我测试它的版本(ideone.com/pFS0Q)。我在网上找不到任何其他版本的Tcl解释器进行测试。