Tclでファイル読み込みする方法

この記事では、Tcl(Tool Common Langueage)について
指定のファイルを読み込む方法を紹介していきます。

Tclは、expectコマンドでも使われている言語なので、その際の参考にしてください。

tclshのインストール方法

tclを試してみる際には、expectコマンドを使って実行するでもよいですが、
tclshというのを使って実行するのが王道です。

インストール方法は、Ubuntuであれば、下記の通り。
tclパッケージをインストールします。

$ # インストール方法
$ sudo apt install tcl

$ # インストール場所の確認
$ which tclsh
/usr/bin/tclsh

インストール後は、tclsh が使えるようになります。

ファイルの読み込みに必要なコマンド(関数)

ファイル読み込みは、open, close, eof, getsあたりを知っていれば実現できます。
そして、ファイルが存在するかどうかチェックするために、fileという組み込みコマンド(関数)もあります。

それぞれについて、最低限しっておきたいコマンドのUsageだけ載せておきます。

参考: Tclの組み込みコマンドの詳細
https://www.tcl.tk/man/tcl8.5/TclCmd/contents.html

参考: Tclチュートリアル
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl24.html
https://www.tcl.tk/man/tcl8.5/tutorial/Tcl25.html
(下記Usageは、上記URLより引用)

open

open fileName ?access? ?permission?

  Opens a file and returns a token to be used when accessing the file via gets, puts, close, etc.

  FileName is the name of the file to open.

  access is the file access mode
    r   ...Open the file for reading. The file must already exist.
    r+   ...Open the file for reading and writing. The file must already exist.
    w    ...Open the file for writing. Create the file if it doesn't exist, or set the length to zero if it does exist.
    w+   ...Open the file for reading and writing. Create the file if it doesn't exist, or set the length to zero if it does exist.
    a    ...Open the file for writing. The file must already exist. Set the current location to the end of the file.
    a+   ...Open the file for writing. The file does not exist, create it. Set the current location to the end of the file.

  permission is an integer to use to set the file access permissions. 
  The default is rw-rw-rw- (0666). 
  You can use it to set the permissions for the file's owner, the group he/she belongs to and for all the other users. 
  For many applications, the default is fine.

指定ファイルへアクセス操作するためトークンを返す。
gets, closeなどのコマンドで使用することになる。

access(読み取り専用など)と、
permission(書き込み時に使うファイルパーミッション)は省略可能。

close

close fileID

  Closes a file previously opened with open, and flushes any remaining output.

ファイルのクローズ、書き込みバッファの内容もflushして閉じる。

eof

eof fileID
  returns 1 if an End Of File condition exists, otherwise returns 0.

ファイル終端に来たら1を返す、それまではゼロを返す。

gets

gets fileID ?varName?

  Reads a line of input from FileID, and discards the terminating newline.
  If there is a varName argument, gets returns the number of characters read (or -1 if an EOF occurs), and places the line of input in varName.

  If varName is not specified, gets returns the line of input. An empty string will be returned if:

  There is a blank line in the file.
  The current location is at the end of the file. (An EOF occurs.)

一行分の文字列を取得する。

file

file isfile name

    Returns 1 if file name is a regular file, otherwise returns 0.

指定のファイル名が存在すれば1を返す、でなければゼロを返す。

実装サンプル

指定のファイルを一行ずつ出力するサンプルコードです。
(reader.tcl として実行権限を付与しておきます)

#!/usr/bin/tclsh

# 引数チェック
if { $argc < 1 } {
    puts stderr "$argv0 <file>"
    exit 1
}
set path [lindex $argv 0]

# ファイルの存在チェック
if {! [file isfile "$path"] } {
    puts stderr "\"$path\" is not a file!"
    exit 1
} 

# ファイルの読み込み
set fp [open "$path" r]
set i 0
while {! [eof $fp]} {
    set line [gets $fp]
    incr i

    puts "$i: $line"
}
close $fp

引数チェックの箇所は、$argc で引数が最低一つあることをチェックしています。
なければ、usage文言を出力して終了。

コマンド引数で指定されたファイルが存在するのか事前にチェックしています。
[file isfile <ファイル名>] を使って、判定しています。

最後に、ファイルをopenしてハンドル用のファイルIDを取得します。(変数fpとしています)
開いたファイルハンドルは、closeするのが作法です。

一応スクリプトが終わったタイミングで自動的にcloseはされますが、
もし、書き込み用にopenしたファイルは、書き込みバッファがflushされない(ファイル書き込みされない)まま終了する可能性があるので、明示的にcloseしていおくように心がけるのが良い。

開いたファイルハンドルを使って、eofでファイルファイル終端までシークするようにループさせています。
一行ごとにgetsで文字列を取得できます。
サンプルでは、行番号をつけて標準出力にアウトプットしてるだけですね。

上記のスクリプトファイルを利用した実行結果は下記の通り。

$ # サンプル用のテキストファイルを用意
$ echo "hoge
piyo
foo" > sample.txt

$ # コマンド引数なしで実行すると、usageが出力される。
$ ./reader.tcl
./reader.tcl <file>

$ # 存在しないテキストファイルはエラーが出力される。
$ ./reader.tcl aaaa
"aaaa" is not a file!

$ # 行番号付きでテキストファイルの内容が出力される。
$ ./reader.tcl sample.txt
1: hoge
2: piyo
3: foo
4:

まとめ

Tclは1988年にリリースされていて、34年も前の言語ですが、
未だに保守されて最新パッケージが細かく提供されている状況です。

使いどころは、expectコマンドくらいでしか自分は思いつかないですが、
Tcl自体の機能を知っていると、expectと組み合わせて結構なんでもできる気がしています。

例えば、今回のサンプルを応用すれば、
ssh接続自動化の際に、パスワードもTclでロードしてくる。なんてこともできますね。

タイトルとURLをコピーしました