文字列

Tclは、文字列処理を基本としたコマンド言語なので、文字列操作は得意です。
通常、if,while,forの制御文では以下の様に簡単に文字列の比較ができます。

set str "abc"
if {$str == "abc"} {
    puts 等しい
}

しかし、if,while,forの制御文は内部でexprコマンドを呼び出しているので、
以下の様に数字と認識できる文字列を比較しようとすると、
数字に変換した後の文字列で比較するので都合が悪いこともあります。

set str 16
if {$str == "0x10"} {
    puts 等しい
}

switch文は、内部でexprコマンドを呼ばないので、文字列の比較になります。
逆に、文字列の比較になるので数字の比較はできません。

set str 16
switch -- $str  {
    0x10    {puts 等しくない}
    16      {puts 等しい}
    default {puts 等しい?}
}

switch文で、正規表現によるパターンマッチを行うときは、-regexpか-globオプションを指定します。

set str 16
switch -regexp -- $str  {
    0x10    {puts 等しくない}
    16*     {puts 等しい}
    default {puts 等しい?}
}

stringコマンド

if,while,forの制御文で文字列を比較したい場合は、stringコマンドを使った方が安全です。
string compareは、2つの文字列が等しければ0を返します。
string equalは、2つの文字列が等しければ1を返します。

set str abc
if {![string compare $str "abc"]} {
    puts 等しい
}
set str abc
if {[string equal $str "abc"]} {
    puts 等しい
}

string matchコマンドを使うとglob形式の正規表現を使ったパターンマッチもできるので便利です。
string matchは、文字列がパターンにマッチすれば1を返します。

set str abc
if {[string match "ab*" $str]} {
    puts 等しい
}

stringコマンドには以下のオプションがあります。

stringコマンドのオプション
string bytelength stringUnicode(UTF-8)ベースのバイト数を返す。文字数ではありません。
string compare ?-nocase? ?-length int? string1 string2文字列を比較する。2つの文字列が等しければ0を返す。 string1がstring2より辞書順の前であれば-1を、後であれば1を返す。 -nocaseオプションを指定すると英大小文字を区別しません。-lengthオプションで文字数を指定できます。
string equal ?-nocase? ?-length int? string1 string2文字列を比較する。2つの文字列が等しければ1を返す。等しくなければ0を返す。
string first string1 string2 ?startIndex?string2をサーチしてstring1が最初に出現する位置のインデックスを返す。 文字列が見つからなければ-1を返す。startIndexでサーチを開始するインデックスを指定できる。
string index string charIndexstringからcharIndexで指定したインデックスの位置の文字を返す。
string is class ?-strict? ?-failindex varname? stringstringがclassで指定したメンバであれば1を返す。そうでなければ0を返す。 classは、alnum, alpha, ascii, boolean, control, digit, double, false, graph, integer, lower, print, punct, space, true, upper, wordchar, xdigitのいずれか。
string last string1 string2 ?startIndex?string2をサーチしてstring1が最後に出現する位置のインデックスを返す。 文字列が見つからなければ-1を返す。startIndexでサーチを開始するインデックスを指定できる。
string length stringstringの文字数を返す。
string map ?-nocase? charMap stringstringをkeyとvalueのペアで構成されるcharMapによって置換して返す。
string match ?-nocase? pattern stringstringがpatterにマッチしていれば1を返す。そうでなければ0を返す。 patternは、glob形式の正規表現を使う。
string range string first laststringのfirstのインデックスからlastのインデックスまでの文字列を返す。
string repeat string countstringをcount回繰り返した文字列を返す。
string tolower string ?first? ?last?stringを英小文字に変換した文字列を返す。
string totitle string ?first? ?last?stringの最初の文字だけ英大文字に、それ以外の文字は英小文字に変換した文字列を返す。
string toupper string ?first? ?last?stringを英大文字に変換した文字列を返す。
string trim string ?chars?stringの前後の空文字(スペース、タブ、ニューライン、キャリッジリターン)を削除した文字列を返す。空文字以外を削除したいときは、charsに文字を指定する。
string trimleft string ?chars?stringの先頭の空文字(スペース、タブ、ニューライン、キャリッジリターン)を削除した文字列を返す。空文字以外を削除したいときは、charsに文字を指定する。
string trimright string ?chars?stringの後尾の空文字(スペース、タブ、ニューライン、キャリッジリターン)を削除した文字列を返す。空文字以外を削除したいときは、charsに文字を指定する。
string wordend string charIndexstringのcharIndexのインデックスの位置の単語の後尾のインデックスを返す。
string wordstart string charIndexstringのcharIndexのインデックスの位置の単語の先頭のインデックスを返す。

appendコマンド

appendは、引数に指定した変数に文字列を追加するコマンドです。
指定した変数が存在しなれば、変数を作成してから文字列を追加します。

set str abc
append str1 def ghi
set str1
=> abcdefghi

append str2 123 456
set str2
=> 123456

formatコマンドとscanコマンド

formatは、ANSI C言語のprintf関数のように書式に従って文字列を作成します。

format {%s = %d} 0x10 0x10
=> 0x10 = 16

scanは、ANSI C言語のsscanf関数のように書式に従って文字列を分解します。
文字列を分解できた数を返します。

scan JST-9 {%[A-Z]%d} var1 var2
=> 2
set var1
=> JST
set var2
=> -9

regexpコマンドとregsubコマンド

regexpは、正規表現によるパターンマッチにより文字列を分解します。
regexpは、文字列の一部がパターンにマッチしたら1を返します。そうでなければ、0を返します。
以下の例は、URLをprotocol,host,pathに分解しています。

set url http://www.foo.com/hoge/index.html
regexp -- {([^:/]*)://([a-z_\.]+)([a-z_\./]+)} $url match protocol host path
=> 1
set match
=> http://www.foo.com/hoge/index.html
set protocol
=> http
set host
=> www.foo.com
set path
=> /hoge/index.html

regsubは、正規表現によるパターンマッチにより文字列を置換します。
regsubは、置換した文字列の数を返します。置換できなければ、0を返します。
以下の例は、URLの前後の不要な文字列を削除しています。

set url http://www.foo.com/hoge/index.html
regsub -all -- {http://|/index.html} $url {} var
=> 2
set var
=> www.foo.com/hoge

regsubは、置換する文字列に&または\0と\1から\9が含まれていると、
それらをマッチした文字列または部分マッチした文字列に置換します。
以下の例は、2番目に部分マッチした文字列に置換しています。

set url http://www.foo.com/hoge/index.html
regsub -all -- {(http://)|(/index.html)} $url {\2} var
=> 2
set var
=> www.foo.com/hoge/index.html

regexpとregsubの正規表現によるパターンマッチは、複雑ですが、非常に強力です。