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)
}
regsub
Tclのコマンドだけでは、文字列から連続していないすべての二重文字を削除することはできません。先読みシーケンスでの後方参照へのアクセスはサポートされていません。つまり、削除のスキームでは、一致領域の重複に関する問題が必ず発生します。
最も簡単な修正は、結果を格納する変数(以下の最後の引数)が指定されたときに実行された置換の数を返す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で後読みを行うことはできません。
ルックアラウンドの詳細:正規表現チュートリアル-ゼロ幅アサーションの先読みと後読み
編集:うーん...Tcl8.5の後方参照のバグのようです。{(.).*\1}
一致しますが、一致しません{(.)(?=.*\1)}
。について文句を言うInvalid backreference number
。先読みの中に後方参照がなければ、これに対する解決策を見つけることはできません。
それは私がテストしたバージョン(ideone.com/pFS0Q)かもしれません。テストするTclインタープリターの他のバージョンをオンラインで見つけることができません。