如何在tcl中严格使用正则表达式删除重复字符

时间:2012-05-22 05:44:39

标签: regex tcl

如何在TCL中严格使用regexp删除字符串中的重复字符? 例如,我有一个像aabbcddeffghh这样的字符串,我只需要“abcdefgh”字符。我尝试使用lsort unique,我可以获得独特的字符:

join [lsort -unique [split $mystring {}]]

但我只需要使用regexp命令。

3 个答案:

答案 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解释器进行测试。