2

如何在 TCL 中严格使用正则表达式删除字符串中的重复字符?例如,我有一个这样的字符串aabbcddeffghh,我只需要“ abcdefgh”字符。我试过了lsort unique,我能够得到独特的字符:

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

但我regexp只需要使用命令。

4

3 回答 3

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)
}
于 2012-05-22T05:46:31.163 回答
3

您不能仅使用 Tcl 的regsub命令从字符串中删除所有不连续的双字符。它不支持访问前瞻序列中的反向引用,这意味着任何删除方案都必然会遇到重叠匹配区域的问题。

最简单的解决方法是包装在一个while循环中(带有一个空的主体),使用regsub将返回在给定一个变量来存储结果时执行的替换次数的事实(下面的最后一个参数):

set str "mississippi mud pie"
while {[regsub -all {(.)(.*)\1+} $str {\1\2} str]} {}
puts $str;          # Prints "misp ude"
于 2012-05-23T10:06:56.363 回答
1
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 解释器来测试。

于 2012-05-22T06:16:02.493 回答