Tcl文法とコマンド

 

記述規則


1.コマンドライン
2.ブランクとタブコードの機能(アーギュメント区切り)
3.改行コードとセミコロン文字の機能(コマンドライン区切り)
4.ダブルコーテーション引用符の機能(文字列)
5.$文字の機能(変数置換)
6.ブランケット引用符 [ ]の機能(コマンド置換)
7.\文字の機能(バックスラッシュシーケンス)
8.ブレース引用符{ }の機能(置換抑制)
9.
10.定数
11.変数の型
12.変数の名前
13.変数のスコープと寿命
14.配列変数
15.リスト変数とリスト処理
 

1.コマンドライン

Tclの文は、UNIXやMS-DOSのコマンドラインと同じ書式です。
例えばファイルをコピーする場合、
コマンドがCOPY、元ファイル名が第1アーギュメント、コピーファイル名が第2アーギュメントです。

例COPY AAA.DAT BBB.DAT

Tclスクリプトも先頭がコマンドで、そのあとにコマンドが必要とするアーギュメントが続きます。
下記の例ではsetがコマンドでvalと1がアーギュメントです。
(setコマンドは第1アーギュメントに変数名、第2アーギュメントに値を求める代入コマンドです。)

例set val 1

コマンドとアーギュメントのセットはTclスクリプトの最小構成単位です。
アーギュメントをひとつも必要としないコマンドも当然許されます。
以降、コマンドとアーギュメントのセットをコマンドラインと呼びます。


2.ブランクとタブコードの機能(アーギュメント区切り)

ブランク及びタブコードは、コマンドとアーギュメント、及びアーギュメント間の区切りコードです。
つまりコマンド文字列と各アーギュメント文字列は、ブランクかタブで区切らなければならないということです。
連続したブランクやタブはひとつの区切りとして扱われます。
Cをはじめ、他のプログラミング言語はブランクやタブを無視しますが、Tclでは重要な役割を果たすことに注意してください。


3.改行コードとセミコロン文字の機能(コマンドライン区切り)

改行コード及びセミコロン文字は、コマンドラインの区切りコードです。
つまりコマンドラインを一行の中に何個も記述したい場合はセミコロンで区切ります。

例set a 100; set b 200; set c 300

セミコロンがなくても改行コードがあればコマンドラインは完結します。
つまり1行にひとつのコマンドラインしか記述しない場合には必ずしもセミコロンが必要ではありません。

コメント行もコマンドラインのひとつです。
#がコメントコマンドであり、改行かセミコロンまでコメント文字とみなされます。


4.ダブルコーテーション引用符の機能(文字列)

ブランク、タブ、改行コードを含んだアーギュメントをコマンドに渡すには””で挟みます。 

例set address "新潟県糸魚川市字印度"

下記の例では改行コードも含んだ文字列がコマンドに渡されます。つまりコマンドライン区切りコードとしての特殊機能が無効化されています。

例set 景品 "
         一等賞 自動車
         二等賞 ふりかけ
       "
””は特殊記号ですので、コマンドに渡されるアーギュメントには含まれないことに注意してください。

また、" はアーギュメントの先頭に記述されている場合にのみ、上述の機能が働きます。
下記の例では、2つの"は文字としてコマンドにそのまま渡されます。アーギュメントの途中にあるからです。

例set val aaaa"bbbb"

尚、後述の置換子は” ”内にあっても全て働きます。


5.$文字の機能(変数置換)

アーギュメントに記述された$文字は変数置換子です。$が先頭に付いた文字列は変数とみなされ、値に置換されてからコマンドに渡されます。
例えば、下例のコマンドラインがTclパーサーに渡されると、bは変数とみなされて、bの値が100であれば、setコマンドに渡されるアーギュメントはaと100になります。

例set a $b

この置換は1回しか行われません。
つまりbの置換結果が$cであったとしても、cの置換は試まれずに$cの2文字がsetコマンドに渡されます。


6.ブランケット引用符 [ ]の機能(コマンド置換)

アーギュメントに記述された[ ]引用符はコマンド置換子です。
[ ]で挟まれた文字列はコマンドラインとみなされ、その実行結果がひとつのアーギュメントとしてコマンドに渡されます。

例set a [expr 100 * 200 + 30]

上記のコマンドラインがTclパーサーに渡されると、[ ]ではさまれたコマンドラインの計算結果20030がsetコマンドに渡されます。これをコマンド置換と呼びます。
アーギュメント文字列中のいかなる位置にあってもコマンド置換機能は働きます。これはダブルコーテーション引用符と異なる性質です。

例puts "Answer=[expr 10 * 4]"

また、[ ]に改行コードが含まれることも許されます。
[ ]はネスト(入れ子構造)も許されます。


7.\文字の機能(バックスラッシュシーケンス)

\文字はC/C++と同等のバックスラッシュシーケンス機能を持ちます。
例えば改行コードは \n 、水平タブコードは\tと記述できます。

これまで説明してきた置換子の前に\を付けるとそれらは単なる文字として扱われます。

例set msg "\$をつけると変数置換が行われます"
  set msg "\[と\]で挟むとコマンド置換が行われます。"


8.ブレース引用符{ }の機能(置換抑制)

アーギュメントの前後に記述された{ }引用符は、中に含まれるあらゆる特殊文字の機能(置換機能)を無効化し、すべて単なる文字としてコマンドにそのまま渡します。¥文字もそのまま渡されます。

例set a {[set b $c]}

上記のコマンドラインがTclパーサーに渡されると、{ }ではさまれた文字列がそのままsetコマンドにひとつのアーギュメントとして渡されます。それぞれ [ ] $ 文字の特殊機能が奪われますので、コマンド置換も変数置換も行われないのです。

{ }は特殊記号ですので、コマンドに渡されるアーギュメントには含まれないことに注意してください。

また、{ }はアーギュメントの先頭と末尾に記述されている場合にのみ、上述の機能が働きます。これはダブルコーテーション引用符と同じであり、コマンド置換子とは異なる性質です。
下記の例では、{ } は文字としてコマンドにそのまま渡されます。

例set val aaaa{bbbb}


9.式

プログラミング言語では、代入式や数値演算式などのが言語仕様の中に組み込まれています。Tclにもはありますが、これはTclが言語として提供しているものではなく、exprifコマンドが提供しているものです。つまり式をアーギュメントとして受け付けるコマンドにのみC言語相当の数値演算式、論理演算式、関係演算式を記述することができます。

例set a [expr $b * sin($c)]

ifコマンドなどの条件式アーギュメントには、文字列比較も数値比較と同じように記述できます。
例if {($a/2)>10 && $b=="tokyo"} {......


式はオペランドと演算子の組み合わせで構成され、式のなかのブランクは無視されます。
演算子には算術演算子(-,!,*,/,%,+,-)・比較演算子(<,>,<=,>=,==,!=)・論理演算子(&&,||)・ビット演算子(&,|,^,<<,>>,~)・条件演算子((条件式)? a:b)があり、C言語と同機能です。

オペランドには整数や実数、及び数学関数を与えることができます。

数字関数はANSI/Cライブラリ関数が提供されています。
もちろん、数学関数の引数にも式を与えることができます。
 
例expr 2*sin($x)
  expr hypot($x2-$x1,$y2-$y1) + $z


10.定数

Tclが扱う定数は文字列定数のみですが、コマンドごとに様々な記述様式がサポートされています。
数値演算はexprコマンドが受け持ちますので、数値定数表記様式はexprコマンドが受け付ける様式を説明することになります。

整数は先頭の文字を0にすれば8進数、0xにすれば16進数として解釈されます。
実数では指数形式も指定可能です。
整数のみならば演算も結果も整数で求められます。
実数が含まれていれば実数で返されます。


11.変数の型

Tclパーサーが扱う変数の型は文字列だけです(サイズ自動拡張)。
しかし、各種コマンドはTclパーサーから渡された変数値を整数や実数、そして論理型として扱うことに注意してください。
つまり、変数の型はないけれど、データの型はコマンドごとにあるのです。
細かく言うとコマンドが内部で変換しているのです。
当然、整数を扱うコマンドに数字以外の文字列を渡してはエラーになります。
ただし、そのエラーはTclの文法エラーではなく、コマンドへのデータエラーであることを理解してください。
Tclはコマンド間のインターフェイスとして変数処理を提供しているので、その中身については干渉しないのです。


12.変数の名前

変数名には漢字も含めて全ての文字が使えます。
ただし$置換子によって置換されるとき、その名前に演算子や特殊記号が含まれていると、その前までが変数名として認識されてしまい、思わぬエラーが発生します。
例えば abc.def 変数への値セットは成功しますが、$abc.def として参照しようとすると $abc の置換になってしまいます。
この場合には、明示的に変数名を { }引用符で囲みます。
例puts ${abc.def}

なるべく特殊文字は使わない様にするべきです。
なお、FreeSoftNet拡張のTclは変数名に漢字を使っても引用符で囲む必要はありませんが、純正Tclでは囲む必要があります。


13.変数のスコープと寿命

変数の型はコマンドに預けていますが、変数のスコープや変数の寿命はTclパーサーが管理しています。
変数のスコープにはグローバル変数、ローカル変数がサポートされています。
また名前空間内の変数もあります。

ローカル変数はプロシージャ(後述)内に作成され、終了すると自動的に削除されます。
グローバル変数は、変数にアクセスする前に宣言しておかなければなりません。

実際にメモリに作成されるのは、宣言された時ではなく、初めて値がセットされた時です。
したがって、値が設定されていない変数を参照するバグはありえません。
エラーとして検出されます。

全ての変数をunsetコマンドによって削除することが可能です。
これはTclの大きな特長です。
すべての変数がダイナミックに生成、削除できるオブジェクトになっています。

名前空間変数は、実質的にはグローバル変数ですが、いわゆる関数内のstatic変数のように扱える工夫がなされたものです。

グローバル変数の宣言はglobalコマンドで、名前空間変数の宣言はvariableコマンドで行います。
いずれの宣言もされずにプロシージャ内で使用される変数がローカル変数になります。


14.配列変数

配列変数は変数名に( )が付いている変数です。
例えばabc(1)などの変数です。
ただし、配列変数としての宣言や要素数を指定するコマンドはありません。
( )が付いた変数に値がセットされるときに配列変数として認識・登録されます。
同じ名前の配列変数と通常変数を同時に存在させることはできません。
例えば set abc 1 を実行した後に set abc(1) 1 を実行するとエラーになります。
この逆も然りです。
つまり早いモノ順です。
配列変数の要素には文字列も使用できます。
またカンマ(,)やピリオド(.)などで要素を区切れば多次元配列になります。

例set abc(a.b) 100
  set abc(a.c) 200

  set index c
  puts $abc(a.$index)→200が表示

要素数は自動拡張です。
配列オーバーは最も陥りやすいバグですが、Tclではあり得ません。

また、配列の要素をリストとして抽出したり、要素と値が繰り返されるリストから配列変数を作成するコマンドが提供されています。
下記の例では
  人口密度(東京) ←100
  人口密度(埼玉) ←60
  人口密度(群馬) ←30
の配列作成と値のセットを行い、その後に配列の要素をリストとして表示しています。

例array set 人口密度 {
     東京 100
     埼玉 60
     群馬 30
  }
  puts [array names 人口密度] →"東京 埼玉 群馬"が表示される。

array setコマンドは、ダイナミックな構造体変数のような使い勝手を提供してくれます。

配列変数をグローバル変数として宣言したり削除するには変数名だけを与えます。

例global 人口密度
  unset 人口密度


15.リスト変数とリスト処理

Tclの特長にリスト処理があります。
リスト処理とは複数のデータの集まりを、あたかもひとつのデータのように処理することです。
リストデータが格納された変数をリスト変数と呼んだりしますが、リスト変数というものが他の変数と区別されて存在しているわけではありません。
この点が配列変数とは異なります。
リスト構造のデータが格納された変数を単にリスト変数と呼んでいます。

Tclのリストコマンドが扱うリストは極めてシンプルな構造です。
要素がブランク、タブコード、改行コードのいずれかで区切られてひとつの文字列になっている構造です。
ブランクやタブを含む要素は{ }引用符で囲まれています。

例AAAA BBB {CCCC DDDD} EEEE

上記のリストには4つの要素があることになります。
また{ }引用符はリストを入れ子構造にするものであるとも言えます。
上の例で、3番目の要素を取り出すと CCCC DDDD が得られますが、この要素は更に2つの要素から成るリストとして扱うことができます。

実際にリストを扱う際には、上述の構造を意識する必要はありません。
リストを作成したり要素を抽出したりするリストコマンドが提供されています。

例アーギュメントを要素としたリストを生成する
  set LIST [list AAAA BBBB "CCCC DDDD" EEE]

例リストからi番目の要素を取り出す
  set Element [lindex $LIST $i]

例リストの要素を順に変数elemに取り出してのループ処理
  foreach elem $LIST {
    puts $elem
  }

リスト処理はCSV形式のデータを処理する場合などに重宝します。
また、SQL命令でデータベースから表データを抽出しての処理なども、簡潔かつ汎用的に記述することができます。


プロシージャ

プロシージャはTclスクリプトで作成されたコマンドのことです。
すでにTcl組み込まれているコマンドと同じように使えます。
プロシージャはprocコマンドで作成します。
値を返す場合はreturnコマンドを用います。
returnコマンドが書かれていなければ、最後に実行したコマンドの戻り値がプロシージャの戻り値になります。

proc プロシ−ジャ名 変数リスト Tclスクリプト

例proc cal { a b c } {
     return [expr ($a+$b)*$c]
  }

【利用方法】set val [cal 10 20 300]


変数のアドレス渡し(upvar)

アーギュメントに変数名を与え、プロシージャがその変数に値をセットする方式(アドレス渡し)も用意されています。
プロシージャ内ではアーギュメントに渡されてきた変数名をupvarコマンドで内部変数にリンクさせてからアクセスするようにします。
 
例proc cal {a b c answer} {
     upvar $answer ans
     set ans [expr ($a+$b)*$c]
  }
【利用方法】cal 10 20 300 result
      puts "答えは$result"

アーギュメントに渡す変数はあらかじめ存在していなくてもかまいません。
upvarコマンドが(呼び出し側に)作成してくれます。


リストコマンド

リスト処理とは、いくつもの値が1つに取りまとめられ、その集まりを1つの値として取り扱う処理です。
リストは特定の構造をもった文字列として表現されており、そのリストを生成したり、要素の挿入,削除,検索,置換などを行うのがリストコマンド群です。


concat
list
lsearch
 

lappend
llength
lsort
lindex
lrange
join
linsert
lreplace
split

斜体は省略可能なアーギュメント。...は複数指定可能を示す。

concat  $list....

 リストを結合して新しいリストを返す。

lappend  varName  $val....

 変数varNameに要素$val...を追加し結果のリストを返す。

lindex  $list  $index

 リスト$listから$index番目の要素を取り出して返す。$indexは0から。

linsert $list $index $val ...

 リスト$listの$index番目の要素の前に全ての要素$val...を挿入したリストを返す。

list  $val....

 すべての要素$val...を要素としたリストを返す(生成)。

llength $list

 リスト$listの要素数を返す

lrange $list   $first  $last

 リスト$listの$first番目から$last番目までの連続要素をリストとして返す。
 $lastに文字列endを与えると最後の要素までの指定となる。
 先頭が0である。

lreplace $list  $first  $last  $val....

 リスト$listの$first番目から$lastまでの連続要素をすべての要素$valで
 置きかえ、新しいリストを返す。

lsearch  $switch $list  $pattern

 リスト$listから、$switchであたえられたパターンマッチング方式で、
 $patternに合致する最初の要素の順番を返す。
 マッチング方式は-glob -exact -regexpの3種で、-globがデフォルト。
 -exactは完全一致。
 -regexpは正規表現規則。
 -globはglob方式。
 ※glob,正規表現の解説はパターンマッチングを参照してください。

lsort $switch  -command  $com   $direction  $list

 リスト$listの要素をソートしたリストを返す。
 $switchは-integer(整数) -ascii(文字) -real(実数)の3種。
 -asciiがデフォルト。
 $directionは方向スイッチで、-decreasingを指定すると降順となる。

join  $list  $joinString

 リスト$listの要素を$joinStringで結合した文字列を返す。
 $joinStringのデフォルトはスペース。

split  $string  $splitChars

 文字列$stringを、$splitCharsで区切られた文字列を要素としたリストを返す。
 $splitCharsのデフォルトはブランク。
 このコマンドは、joinコマンドと逆の関係にある。

例実行例 Tclsh.exeで実際に実行してみてください。右が実行結果です。
  set List [list bb aa cc {} dd ee]  → bb aa cc {} dd ee
  llength $List         → 6
  lrange $List 2 end     → cc {} dd ee
  lsearch $List cc       → 2
  lindex $List 4        → dd
  lappend List ff gg     → bb aa cc {} dd ee ff gg
  linsert $List 2 xx yy   → bb aa xx yy cc {} dd ee ff gg
  lsort $list          → {} aa bb cc dd ee ff gg
  lreplace $List 1 xx yy   → bb xx yy cc {} dd ee ff
  join $List -         → bb-aa-cc--dd-ee-ee-gg
  split "aa\tbb\tcc\t\tdd" \t → aa bb cc {} dd


制御コマンド

if
foreach
eval
for
break
while
continue
switch
source

斜体は省略可能なアーギュメント。...は複数指定可能を示す。

if { test1} {body1} elseif {test2} {body2} elseif..... else {bodyn}

 test1:body1(Tclスクリプト)を実行する条件式。真ならbody1が実行される
 test2:test1の条件が偽のとき評価される条件式。
     真ならbody2(Tclスクリプト)が実行される
 bodyn:すべての条件が偽のとき実行されるTclスクリプト

for {init} {test} {reinit} {body}

 init:初期設定Tclスクリプト
 test :ループ条件式(真ならループ継続)
 reinit:再設定Tclスクリプト
 body:Tclスクリプト(処理本体)

while {test} {body}

 test:条件式(真ならループ継続)
 body:Tclスクリプト(処理本体)

switch  $switch  $string   {$pattern1 {body} ..... $pattern {body}}

 stringを検査し、合致したpatternのbody(Tclスクリプト)を実行する。
 switchはパターンマッチング方式の指定であり -glob -exact -regexpの3種がある。
 デフォルトは -glob

foreach $valNameList  $list   {body}

 リストlistから要素を取り出して変数valNameListに順に代入後、bodyを実行。
 この処理をlistの先頭要素から最後の要素まで繰り返す。

break

 ループ脱出。for while switch foreachのbodyに記述可

continue

 ループの条件式評価にジャンプ。for while foreachのbodyに記述可

source  $sourceFileName

 Tclスクリプトファイル$sourceFileNameをオープンし内容を実行後、結果を返す。

eval  arg1  arg2 .....

 すべてのアーギュメントをスペースを挟んで結合したあと、
 その文字列をTclスクリプトとして実行し結果を返す。
 コマンドをダイナミックに作成して実行する場合に使用する。


文字列操作コマンド


format
regsub
string last
string match
string toupper
string trimright
 

scan
string compare
string index
string range
string trim
 
regexp
string first
string length
string tolower
string trimleft
 

斜体は省略可能なアーギュメント。...は複数指定可能を示す。

format  $formatString $val ......

 $formatStringはANSII Cに準拠した変換指定子。
 変換指定子の順に、その数だけ値$valを与える。変換結果が返される。

scan  $string $formatString varName .....

 $formatStringの指定に基づいて$stringを解析し変換指定子ごとに
 値をvarNameに代入する。
 正しく変換された数が返される。

regexp   $switches $exp $string varName......

 正規表現$expが$stringに合致するか否か調べ、合致すれば1を、
 しなければ0を返す。
 変数名varNameが与えられていれば合致した文字をセットする。
 $switchesに-nocaseを指定すると大文字小文字の区別が無視される。
 -indicesを指定すると変数にセットされるのは合致した部分文字列の
 インデックスリスト(例"5 8")になる。

regsub  $switches $exp $string $change varName

 regexpと同様の検査をするがglob形式でパターンマッチングを行う。
 さらに、合致する部分を$changeに置き換え、その結果の文字列を変数varNameに
 セットする。
 $switchesに-nocaseを与えると大文字小文字の違いを無視する。
 また-allを与えると$stringの中の合致文字置換はすべてに対して行われる。
 指定しないと合致した最初の文字列だけの置換となる。

string compare  $string1 $string2

 $string1と$string2を辞書順で調べ、1が2より小さい、等しい、大きいの順で
 -1,0,1を返す

string first   $string1 $string2

 $string2の中で最初に$string1に合致した部分文字のインデックスを返す。
 合致しなければ-1を返す。

string last   $string1 $string2

 $string2の中で最後に$string1に合致した部分文字列の先頭インデックスを返す。

string index   $string1 $string2

 $stringの中から$index番目の文字を返す。
 範囲外なら空文字を返す。

string length   $string

 $stringの文字数を返す。

string match   $pattern $string

 glob形式のマッチング規則で、$pattenが$stringに合致していれば1を
 不合致なら0を返す。

string range   $string $first $last

 $stringの$firstから$last番目までの文字列を返す。

string tolower  $string

 $stringを小文字変換して返す。

string toupper   $string

 $stringを大文字変換して返す。

string trim   $string $removeChars

 $stringの両脇にある$removeCharsを取り除いた文字列を返す。

string trimleft   $string $removeChars

 string trimと同じだが先頭文字だけが切り捨てられる。

string trimright   $string $removeChars

 string trimと同じだが末尾文字だけが切り捨てられる。

例実行例 Tclsh.exeで実際に実行してみて下さい。右が実行結果です。
  set txt AABBCCDDEEFFGGHHAA
  string length $txt     → 18
  string index $txt 2    → B
  string range $txt 0 5  → AABBCC
  string range $txt 6 end → DDEEFFGGHHAA
  string trim $txt A    → BBCCDDEEFFGGHH
  string trimleft $txt A  → BBCCDDEEFFGGHHAA
  string trimright $txt A  → AABBCCDDEEFFGGHH
  string tolower $txt    → aabbccddeeffgghhaa
  string compare $txt AABB → 1
  string first CCD $txt   → 4
  string last AA $txt    → 16
  regexp B* $txt       → 1
  regsub -all AA $txt ZZZ newtxt  → ZZZBBCCDDEEFFGGHHZZZ
  format “%6.6s” $txt        → AABBCC


パターンマッチング(glove 正規表現)

regexp,regsub,string match,switchコマンドなどが文字列を比較するとき、その比較方法(パターンマッチング)にglob形式正規表現が用いられます。

glob型式

glob形式とは、OSにファイル名を指定するときに用いられる馴染みの深い方法です(DIR *.dat など)。
glob形式では次の特殊文字が使えます。

*    任意の長さ(ゼロを含む)の文字列
?    任意の1文字
[chars] charsのなかのいずれか1文字 [a-d]という指定は [abcd]と同
\    特殊記号の前につけ、単なる文字としての扱いを指定

例123ABC* の文字列に対するマッチング結果
  *ABC      真
  ABC*      偽
  ???????     真
  ??????     偽
  ???A?C?     真
  ????A?C     偽
  ??????\*    真
  [0-9]*     真
  [A-Z]*     偽
  *[A-Z]*     真
  *[D-Z]*     偽
  ?2??B??     真


正規表現

glob形式の弱点は「文字列が数字のみから構成されているか」というような指定ができないことです。
[0-9]はひとつの文字に対する評価であり、もし3桁の数字か否かを評価するには[0-9][0-9][0-9]と指定しなければならず、とても冗長です。しかも桁数の指定も伴ってしまいます。

これに対し、正規表現は強力です
[0-9]+ と指定するだけで、桁数を問わず数字のみで構成されている文字列か否かを判定できます。
+は「直前の文字の1つ以上の繰り返し」という意味を持ちます。

正規表現では下記の特殊文字が使えます。

.    任意の1文字
^    文字列の先頭
     ただし[chars]書式のcharsの先頭につけられるとNOTの意味をもつ
$    文字列の終わり
[chars] charsのなかのいずれか1文字 [a-d]という指定は [abcd]と同
     charsの先頭が]の場合は]は文字として扱われる。
     charsの先頭または末尾の-は文字として扱われる。
*    直前の要素の0回以上の繰り返し
+    直前の要素の1回以上の繰り返し
?    直前の要素がなくても可
( )   グループ指定  部分文字列
|    OR
\    特殊記号の前につけ、単なる文字としの扱いを指定

正規表現は文字ひとつひとつについて指定していきます。それらを要素と呼びます。
要素は文字か[ ]で与えられる文字範囲です。
それらの要素を( )で挟んでグループ化すると、ひとつの要素として扱われます。

要素の繰り返しを * +で指定できます。
?はその要素がない場合も可とするものです。
*+?を演算子と考え、( )でグループ化できることを考えると、正規表現は多項式の構造をもっており、文字列の構造式と呼べるものであることがわかります。

例16進数として正しく記述されている文字列か否かを判定する正規表現を考えてみます。
まず「先頭に0xが付いていてもいなくても可とする」は ^(0x)? と表現されます。
( )で挟んで要素0とxをグループ化し0xの文字列を生成しています。
^は文字列の先頭(0xの前に文字はない)を表しています。
?は直前の要素―即ち0xがあってもなくても良いことを表しています。

つぎに「16進数に使える文字」を指定します。
それは[0-9a-fA-F]と表現されます。
そしてこれらの文字が繰り返して現れるのであるから+を付けて [0-9a-fA-F]+ となります。
これらの文字だけが連続したあと「文字列は終了する」ことを表す$を末尾につけて、最終的に下記の正規表現となります。
    ^(0x)?[0-9a-fA-F]+$

これをregexpコマンドに与えて文字列を評価すると下記の例となります。 
  regexp {^(0x)?[0-9a-fA-F]+$} 0x25AF →1
  regexp {^(0x)?[0-9a-fA-F]+$} 25af  →1 (正規表現の?が+なら0です)
  regexp {^(0x)?[0-9a-fA-F]+$} 25aG  →0 (正規表現に$がなければ1です)
  regexp {^(0x)?[0-9a-fA-F]+$} 0x   →0 (正規表現の+が?なら1です)

正規表現をアーギュメントにして渡す時は必ず{ } ではさんで下さい。
正規表現の特殊文字がTclの特殊記号と重複しているからです。
正規表現は、その解釈のアルゴリズムを考えるともっと理解が深まります。

正規表現によるパターンマッチングは次のように処理されます。
まず正規表現の最初の要素を取り出します。
その要素で文字列の先頭文字を評価します。
合致していなければ次の文字を調べ、これを合致するまで繰り返します。
合致する文字が現れたら次の要素を取り出します。
その要素が+記号だったら前回の要素で、次の文字を評価します。
これも合致していれば次の文字を評価し、合致しない文字が現れるまでこれを繰り返します。
+記号はそのような処理を要求するものです。
合致しない文字が現れたら、次の要素を取り出してその文字を評価します。
このような手順で評価をすすめ、全要素について評価がすめば最終判断として合致(TRUE)を返します。

気を付けるべきことは、全要素の評価が終わらないうちに合致判断はされないが、文字列の全文字を調べなくても全要素の評価がすめば合致判断されるということです。
例えば文字列が12345のとき、正規表現234でのマッチングは4の文字が評価された段階で合致判定されます。
ただし^と$記号で要素が挟まれていれば全文字列の評価が行われます(正規表現が ^234$ なら評価はFALSEです)。

正規表現はglob形式より複雑ですが、複雑な文字列評価が1行でプログラミングできますのでTclの強力な文字処理機能の代表格と言えるものです。


ファイル操作コマンド

cd
gets
eof
pwd
open
read
file
close
seek
flush
puts
tell
glob

斜体は省略可能なアーギュメント。...は複数指定可能を示す。

cd $dirName

 作業ディレクトリィを変更する。

open $fileName $access

 ファイルを開きファイル識別子を返す。
 $accessはr,r+,w,w+,a,a+のいずれか。
 デフォルトはr。

close $fileId

 ファイルを閉じる。

puts $option $fileId  $string

 文字列$stringを識別子$fileIdのファイルに書く。
 $fileIdを省略するとstdoutに出力される。
 $optionに-nonewlineを指定しないと改行コードが書かれる。

gets $fileID varName

 識別子$fileIdのファイルから文字列を読み込み、変数varNameに代入し
 その文字数を返す。
 ファイル末尾に達した場合は-1を返す。
 変数名が省略されると文字列を返す。
 末尾に達した場合は空文字を返す。

read $option $fileId

 識別子$fileIdのファイルから残りのデータをすべて読み込み、それらを返す。
 -nonewlineが指定されている場合には末尾に改行コードがあれば削除される。

seek $fileId $offset $origin

 識別子$fieldIdファイルのアドレス$offsetにシークする。
 $originはstart,current,endのいずれか。
 省略するとstart。

tell $fileId

 識別子$fileIdファイルの現在のアクセス位置を返す。

eof $fileId

 識別子$fileIdファイルのアクセス位置がeofに達している場合は1を、
 それ以外の場合は0を返す。

file $option $fileName arg...

 ファイル名$fileNameのファイルに$optionで与えた操作を行う。
 $optionは下記のいずれか。

atime

最後に参照された時刻を返す

dirname

ファイル名からディレクトリ名を取り出す

executable

実行可能なら1を返す

exists

存在し、アクセス可能なら1を返す

extension

ファイルの拡張子を取り出す

isdirectory

ディレクトリファイルなら1を返す

isfile

通常のファイルなら1を返す

lstat

lstatのシステムコールを実行しargで与えた変数に結果を返す

mtime

最後に修正された時刻を返す

owned

現在のオーナーが自分なら1を返す

readable

読み込み可能なら1を返す

readlink

リンクファイル名を返す

rootname

最後のドットまで(ドットは含まない)の文字列を返す

size

ファイルサイズを返す

stat

システムコールstatを実行し、argで与えた変数に結果を返す

tail

ファイル名を返す

type

ファイルの種類を返す。種類はfile,directory,など

writable

ファイルが書き込み可能なら1を返す

flush $fileId

 バッファに蓄積されているデータを識別子$fileIdのファイルに吐き出す。

glob $switch $pattern $pattern..

  $patternに合致するすべてのファイル名のリストを返す。

pwd

 現在の作業ディレクトリ名を返す。


内部情報の取り出し(Infoコマンド)

infoコマンドはTclインタープリタが保持している内部情報を取り出します。

info+

args
commands
exists
library
patchlevel
tclversion
body
complete
hostname
locals
procs
vars
cmdcount
default
level
nameofexecutable
script
  

info args $procname

 $procname(プロシージャ名)のアーギュメントリストを返す(bodyを参照)。

info body $procname

 $procname(プロシージャ名)の中身を返す。
例tclsh.exe
  % proc test {a b } {
  % return [expr $a * $b]
  % }
  % info args test
  % a b
  % info body test
  % return [expr $a * $b]

info cmdcount

 プロシージャが現在までに実行したコマンド数を返す。
 info cmdcount自身も数に含まれる。
 ※ブラケットで囲まれたコマンドの実行(コマンド置換)は数にふくまれません。

info commands $pattern

 $pattern(プロシージャ名の検索文字-glob型式・省略可)に、合致する
 プロシージャのリストを返す。
 内部コマンドも含まれる。
 $patternを省略すると全てのコマンド・プロシージャのリストを返す。

info complete $command

 $command(コマンドライン)に与えられたコマンドラインが正しく完結しているか
 調べる。
 完結していれば1を返す。
 ダブルクオートやブラケットなどが閉じていない場合は0を返す。

例tclsh.exe
  % info complete {set a "this is a pen}
  % 0
  % info complete {set a "this is a pen"}
  % 1

info default $procname $arg varname

 $procname(プロシージャ名)の$arg(そのプロシージャの中のひとつの
 アーギュメント名)のデフォルト値を調べる。
 デフォルト値を持たない場合は0を返す。
 デフォルト値をもつならばその値をvarnameにセットして1を返す。

例tclsh.exe
  % proc test {{a 3} b} {
  % return [expr $a * $b]
  % }
  % info default test b var
  % 0
  % info default test a var
  % 1
  % puts $var
  % 3

info exists varname

 変数varnameが存在するか調べる。

info hostname

 PCのホスト名を返す。

info level $number

 $number (コマンド階層・省略可)を省略すると現在の階層番号を返す。
 $number を与えると、その階層のプロシージャ名を返す。
 $number は自分の階層より小さい値(上層)を指定する(1以上)。
 例えば、testプロシージャからコールされるtest2プロシージャ内で
 info levelを実行すると2がリターンされる。
 そして、続けてinfo level 2を実行するとtest2が返され
 info level 1を実行するとtestが返される。

info library

 ライブラリが格納されているディレクトリを返す。
 これはグローバル変数 tcl_libraryの値。
 sourceコマンドにおける、tclソースファイルのデフォルト格納先である。

info locals $pattern

 ローカル変数リストを返す。
 $pattern(変数名の検索文字列・glob型式・省略可)を省略すると
 全てのローカル変数名リストを返す。
 $patternを与えると合致するローカル変数リストのみを返す。
 ローカル変数とはglobalおよびupvarで宣言されていない、プロシージャ内部の
 変数で、ローカル変数にはプロシージャのアーギュメントも含まれる。

info nameofexecutable

 実行ファイル名を返す。
例tclsh.exe
   % info nameofexecutable
   % A:\WinGeo\tclsh.exe

info patchlevel

 グローバル変数tcl_patchLevelの値を返す。

info procs $pattern

 $pattern(変数名の検索文字列・glob型式・省略可)を省略すると、
 現在の名前空間内の全てのプロシージャ名リストを返す。
 $patternに名前空間名を検索文字として与えると、その名前空間内に
 定義されたプロシージャ名リストを返す。

info script

 tclソースファイル名を返す。
 sourceコマンドで評価されるソースファイル内に記述されたとき有効。

info tclversion

 tclのバージョンを返す。

info vars $pattern

 現在アクセスできるグローバル及びローカル変数リストを返す。
 $pattern(変数名の検索文字列・glob型式・省略可)を省略すると
 全ての変数名リストを返す。
 $patternを与えると合致する変数リストのみを返す。
 変数にはプロシージャのアーギュメントも含まれる。

 

(C)FreeSoftNet,Inc.