<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Tcl/Tk | ITドカタ</title>
	<atom:link href="https://blog.it-see.net/it-dokata/category/tcl-tk/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.it-see.net/it-dokata</link>
	<description>ICT関連の役立つかもしれない情報を発信するブログ。</description>
	<lastBuildDate>Tue, 19 Apr 2022 14:21:44 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.5</generator>

<image>
	<url>https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/05/cropped-job_it_dokata2-32x32.png</url>
	<title>Tcl/Tk | ITドカタ</title>
	<link>https://blog.it-see.net/it-dokata</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>tclshでBash(シェル)のようなコマンド履歴機能を使うには</title>
		<link>https://blog.it-see.net/it-dokata/tcl-tk/tclsh-command-history/</link>
		
		<dc:creator><![CDATA[いっしー]]></dc:creator>
		<pubDate>Thu, 12 Aug 2021 11:08:05 +0000</pubDate>
				<category><![CDATA[Tcl/Tk]]></category>
		<guid isPermaLink="false">https://blog.it-see.net/it-dokata/?p=1947</guid>

					<description><![CDATA[Tclインタプリタにはコマンド履歴機能がありません。この記事ではtclshとrlwrapコマンドを組み合わせてヒストリ機能を使う方法を紹介します。 目次 Tclを対話的に実行するtclshとrlwrapコマンドを組み合わ [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Tclインタプリタにはコマンド履歴機能がありません。この記事ではtclshとrlwrapコマンドを組み合わせてヒストリ機能を使う方法を紹介します。</p>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>




  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-2" checked><label class="toc-title" for="toc-checkbox-2">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">Tclを対話的に実行する</a></li><li><a href="#toc2" tabindex="0">tclshとrlwrapコマンドを組み合わせて使う</a></li><li><a href="#toc3" tabindex="0">rlwrapのインストール</a><ol><li><a href="#toc4" tabindex="0">EPELのインストール</a></li></ol></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">Tclを対話的に実行する</span></h2>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<p>tclshを引数なしで実行するとTclインタプリタが起動し、Tclコマンドの入力待ち状態になります。この状態でTclコマンドを入力する事で対話的にコマンドを実行する事ができます。</p>



<p>この機能はコマンド動作のちょっとした確認をする際に便利です。しかし、TclインタプリタにはBash(Unixシェル)のようなコマンド履歴機能がなかったり、左右の矢印キーでコマンドライン上を移動できないのでシェルとしては使いやすいとは言えません。</p>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[実行例]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">$ tclsh
% set x hello!
hello!
% puts $x
hello!
% ^[[A   ← 上矢印キーを押すとこのようになります。</pre>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<p><span class="bold"><span class="marker-under-red">上矢印キーを押すと実行例のように「 ^[[A 」が表示されコマンド履歴を表示する事ができません。</span></span></p>



<p><span class="marker-under">※WindowsのコマンドプロンプトやPowerShellでは上矢印キーでコマンド履歴を表示します。</span></p>



<p>Bash、tcsh、zshのようなUnixシェルにはコマンド履歴機能(ヒストリ機能)があり、カーソルキーで過去に入力したコマンドを呼び出す事ができます。</p>



<p>これと同じ機能がtclshを起動した時にも使えるようにする方法を紹介します。</p>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<div class="blogcard-shortcode-wrap paragraph">[参考]<br>
<a rel="noopener" href="https://wiki.tcl-lang.org/page/rlwrap" title="rlwrap" class="blogcard-wrap external-blogcard-wrap a-wrap cf" target="_blank"><div class="blogcard external-blogcard eb-left cf"><div class="blogcard-label external-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail external-blogcard-thumbnail"><img decoding="async" src="https://s.wordpress.com/mshots/v1/https%3A%2F%2Fwiki.tcl-lang.org%2Fpage%2Frlwrap?w=160&#038;h=107" alt="" class="blogcard-thumb-image external-blogcard-thumb-image" width="160" height="107" /></figure><div class="blogcard-content external-blogcard-content"><div class="blogcard-title external-blogcard-title">rlwrap</div><div class="blogcard-snippet external-blogcard-snippet">Tclers wiki</div></div><div class="blogcard-footer external-blogcard-footer cf"><div class="blogcard-site external-blogcard-site"><div class="blogcard-favicon external-blogcard-favicon"><img decoding="async" src="https://www.google.com/s2/favicons?domain=https://wiki.tcl-lang.org/page/rlwrap" alt="" class="blogcard-favicon-image external-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain external-blogcard-domain">wiki.tcl-lang.org</div></div></div></div></a></div>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc2">tclshとrlwrapコマンドを組み合わせて使う</span></h2>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<p><strong><span class="marker-under-red">tclshとrlwrapコマンドを組み合わせる事により矢印キーでコマンド履歴を呼び出せます。</span></strong></p>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[実行例]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">$ rlwrap tclsh
% set x hello!
hello!
% puts $x
hello!
% puts $x ←上矢印キーを押すと直前のコマンドを表示します。</pre>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<p>環境設定ファイルに以下の設定を追加する事で、rlwrap を入力せずに済みます。</p>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<p>Bシェル系</p>



<pre class="nohighlight">alias tclsh='rlwrap tclsh'</pre>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<p>Cシェル系</p>



<pre class="nohighlight">alias tclsh 'rlwrap tclsh'</pre>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<p>環境設定ファイルは、.profile、.bashrc、.cshrcなど。自分の環境に合わせてください。</p>



<p>rlwrapの詳し使い方はman rlwrap などで調べてください。</p>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc3">rlwrapのインストール</span></h2>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<p>rlwrapがない場合はインストールしてください。</p>



<p>[実行例]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">$ rlwrap tclsh
bash: rlwrap: コマンドが見つかりませんでした...</pre>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[CentOS 7 の例]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">$ sudo yum -y install rlwrap</pre>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[FreeBSDの例]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;"># pkg install rlwrap</pre>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<p><span class="bold"><span class="marker-under-red">CentOSの場合、EPEL(Extra Packages for Enterprise Linux)が使える環境でないとインストールできません。その場合、次の項目を参照してください。</span></span></p>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc4">EPELのインストール</span></h3>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">$ sudo yum install epel-release</pre>



<p>上記でインストールできな場合は、次のようにEPELのソースをダウンロードしてインストールしてください。</p>



<p>[EPELのダウンロード]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">$ sudo wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
</pre>



<p>[EPELのインストール]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">$ sudo rpm -ivh epel-release-latest-7.noarch.rpm
</pre>



<p>[EPELリポジトリを有効化する]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">$ sudo yum-config-manager --enable epel</pre>



<p>EPEが使えるようになったら次のコマンドでrlwrapをインストールします。</p>



<p>[rlwrapコマンドのインストール]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">$ sudo yum -y install rlwrap
</pre>



<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div>



<p></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Tcl &#8211; パイプラインの活用 -プロセス間通信-</title>
		<link>https://blog.it-see.net/it-dokata/tcl-tk/pipe/</link>
		
		<dc:creator><![CDATA[いっしー]]></dc:creator>
		<pubDate>Fri, 13 Dec 2019 10:58:30 +0000</pubDate>
				<category><![CDATA[Tcl/Tk]]></category>
		<guid isPermaLink="false">https://blog.it-see.net/it-dokata/?p=1438</guid>

					<description><![CDATA[目次 外部プログラムとのデータの受け渡しパイプの機能Tclでパイプを開く外部プログラムの標準出力からデータ受け取る外部プログラムの標準入力へデータを渡す双方向にパイプを開く 外部プログラムとのデータの受け渡し 外部プログ [&#8230;]]]></description>
										<content:encoded><![CDATA[

  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-4" checked><label class="toc-title" for="toc-checkbox-4">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">外部プログラムとのデータの受け渡し</a></li><li><a href="#toc2" tabindex="0">パイプの機能</a></li><li><a href="#toc3" tabindex="0">Tclでパイプを開く</a><ol><li><a href="#toc4" tabindex="0">外部プログラムの標準出力からデータ受け取る</a></li><li><a href="#toc5" tabindex="0">外部プログラムの標準入力へデータを渡す</a></li><li><a href="#toc6" tabindex="0">双方向にパイプを開く</a></li></ol></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">外部プログラムとのデータの受け渡し</span></h2>



<p>外部プログラムの起動とデータの受け渡しはexecコマンドで説明しましたが、他の方法としてopenコマンドを使う方法があります。</p>



<p>execコマンドは、入出力のデータ量が少なくプログラムの実行時間が短い場合はいいですが、実行に時間がかかるプログラムでは以下の問題があります。</p>



<ul class="wp-block-list"><li>execコマンドで起動したプログラムが終了するまで、処理を再開できない。</li><li>execコマンドで起動したプログラムが終了した時に、プログラムの出力が一度に返って来る。</li></ul>



<p>この問題を解決するにはopenコマンドでパイプを開いて送受信するようにします。</p>



<p>openコマンドはファイルだけでなくパイプを開くことができます。openコマンドを使用したデータの受け渡しは、開いたパイプを通して外部プロクラムとデータの受け渡しを行います。</p>



<p>この機能を使うとファイルの入出力と同じようにパイプをクローズするまで、起動したプログラムとデータの受け渡しができるようになります。</p>



<p>OSは起動したプログラムをプロセスという単位で管理しています。<span class="marker-under">起動したプロセスからさらにプロセスを起動すると、起動元を<strong>親プロセス</strong>、起動したプロセスを<strong>子プロセス</strong>といいます。</span>プロセス同士でデータの受け渡しをすることを<strong>プロセス間通信</strong>といいます。</p>



<p><strong><span class="marker-under">Tclではopenコマンドを使ってプロセス間通信をする事ができます。</span></strong></p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc2">パイプの機能</span></h2>



<p>パイプは、標準出力を次のコマンドの標準入力へ繋げる機能があります。</p>



<p>Unixでは、以下の例のようにコマンドの出力結果を次のコマンドの標準入力へ繋げて使うことがよくあります。Windowsでもコマンドプロンプト画面で使えますが、基本的にGUI操作がメインなので使ったことがない方もいるかも知れません。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[使用例]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;"># 各ファイルのディスク使用量を確認する

$ du -ah tcl-tk | more
4.0K	tcl-tk/hello.tcl
4.0K	tcl-tk/hello-w.tcl
4.0K	tcl-tk/input.tcl
　　　　　・
　　　　　・
4.0K	tcl-tk/swap.tcl
4.0K	tcl-tk/sum.tcl
--続ける--

# 行番号付で表示する。

$ cat hello-w.tcl | nl
     1	#!/bin/sh
     2	# the next line restarts using tclsh \
     3	exec wish "$0" "$@"
       
     4	# hello-w.tcl
       
     5	message .msg -width 200 -text {hello, world!}
     6	button .btn -text 終了 -command exit
     7	pack .msg .btn

# (3)小文字を大文字に変える。

$ echo "hello" | tr a-z A-Z
HELLO
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc3">Tclでパイプを開く</span></h2>



<p>ファイルの入出力の記事で<a aria-label="openコマンド (新しいタブで開く)" href="https://blog.it-see.net/it-dokata/tcl-tk/file-io-operetion/#toc6" target="_blank">openコマンド</a>を紹介しましたが、このコマンドは、ファイル名の代わりに「|(pipe)」を指定することも出来ます。</p>



<p>パイプを使うと外部のプログラムとデータの受け渡しをすることができます。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<div class="wp-block-image"><figure class="aligncenter"><img fetchpriority="high" decoding="async" width="865" height="583" src="https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/12/外部コマンドとのデータの受け渡し.png" alt="" class="wp-image-1441" srcset="https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/12/外部コマンドとのデータの受け渡し.png 865w, https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/12/外部コマンドとのデータの受け渡し-300x202.png 300w, https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/12/外部コマンドとのデータの受け渡し-768x518.png 768w, https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/12/外部コマンドとのデータの受け渡し-120x80.png 120w, https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/12/外部コマンドとのデータの受け渡し-160x107.png 160w" sizes="(max-width: 865px) 100vw, 865px" /></figure></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>openコマンドによるパイプの使い方をいくつか紹介します。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc4">外部プログラムの標準出力からデータ受け取る</span></h3>



<div class="wp-block-image"><figure class="aligncenter"><img loading="lazy" decoding="async" width="706" height="145" src="https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/12/外部プログラムの標準出力からデータを受け取る.png" alt="" class="wp-image-1442" srcset="https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/12/外部プログラムの標準出力からデータを受け取る.png 706w, https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/12/外部プログラムの標準出力からデータを受け取る-300x62.png 300w" sizes="(max-width: 706px) 100vw, 706px" /></figure></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[書式]</p>



<pre class="nohighlight"><strong>set</strong> <em>varName</em> [<strong>open</strong> "| program" "r"]
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>アクセスモードに&#8221;r&#8221;を指定してパイプを開くとprogramの標準出力チャネルから出力されたデータをgetsコマンドまたはreadコマンドで受け取ることができます。</p>



<p>execコマンドと違い、closeコマンドでパイプを閉じる必要があります。varNameにはファイル識別子がセットされます。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[使用例]</p>



<pre class="tcl">set fid [open "| df -h" "r"]
set str [read -nonewline $fid]
puts $str
</pre>



<p>[出力]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">ファイルシス        サイズ  使用  残り 使用% マウント位置
/dev/mapper/cl-root    17G  5.7G   12G   34% /
devtmpfs              903M     0  903M    0% /dev
tmpfs                 920M     0  920M    0% /dev/shm
tmpfs                 920M  9.5M  910M    2% /run
tmpfs                 920M     0  920M    0% /sys/fs/cgroup
/dev/sda1            1014M  386M  629M   38% /boot
vbox共有              356G  176G  180G   50% /media/sf_vbox共有
tmpfs                 184M   24K  184M    1% /run/user/1000
/dev/sr0               56M   56M     0  100% /run/media/xxxx/VBox_GAs_5.2.26
tmpfs                 184M  4.0K  184M    1% /run/user/42
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc5">外部プログラムの標準入力へデータを渡す</span></h3>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="711" height="164" src="https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/12/外部プログラムの標準入力へデータを渡す.png" alt="" class="wp-image-1443" srcset="https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/12/外部プログラムの標準入力へデータを渡す.png 711w, https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/12/外部プログラムの標準入力へデータを渡す-300x69.png 300w" sizes="(max-width: 711px) 100vw, 711px" /></figure>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[書式]</p>



<pre class="nohighlight"><strong>set</strong> <em>varName</em> [<strong>open</strong> "| program" "w"]
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>アクセスモードに&#8221;w&#8221;を指定して開くと、putsコマンドでprogramの標準入力へデータを渡すことができます。</p>



<p>execコマンドと違い、closeコマンドでパイプを閉じる必要があります。varNameにはファイル識別子がセットされます。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[使用例]</p>



<pre class="tcl">set fid [open "| cat" "w"]
puts $fid "Hello! Hello!\nGood morning!"
flush $fid
</pre>



<p>[出力]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">Hello! Hello!
Good morning!
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>上の例のように、putsコマンドで外部プログラムにデータ送る場合、バッファリングの問題があるのでflushコマンドで吐き出す必要があります。</p>



<p>※バッファリングについては「<a aria-label="Tcl - 文字列の入力と出力について -標準入出力- (新しいタブで開く)" href="https://blog.it-see.net/it-dokata/tcl-tk/string-input-and-output-in-tcl/#toc3" target="_blank">Tcl &#8211; 文字列の入力と出力について -標準入出力-</a>」で紹介しています。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>もう1つの方法としてfconfigureコマンドまたはchanコマンドで、バッファリングモードを変更しておくこともできます。</p>



<p>[書式]</p>



<pre class="nohighlight"><strong>fconfigure</strong> <em>channelId -buffering newValue</em> 
<strong>chan configure</strong> <em>channelId -buffering newValue</em>
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>newValueは次の値を指定できます。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<table class="wp-block-table aligncenter"><tbody><tr><th> newValue </th><th>意味</th></tr><tr><td>full </td><td>バッファが一杯になると書き出す。(デフォルト)</td></tr><tr><td>line</td><td>改行文字ごとに書き出す。</td></tr><tr><td>none</td><td>出力操作の実行直後に自動的に書き出す。</td></tr></tbody></table>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[使用例：chanコマンドの例]</p>



<pre class="tcl">set fid [open "| cat" "w"]
chan configure $fid -buffering line
puts $fid "Hello! Hello!\nGood morning!"
close $fid
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc6">双方向にパイプを開く</span></h3>



<p>[書式]</p>



<pre class="nohighlight"><strong>set</strong> <em>varName</em> [<strong>open</strong> "| program" "r+"]
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>アクセスモードに&#8221;r+&#8221;を指定して開くと、データの受け取り、受け渡しの双方向のパイプを開くことができます。</p>



<p>この方法は、起動したプログラム(子プロセス)側も出力をバッファリングしないようにしなければ上手く通信が出来ません。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">送受信の都度、子プロセスを起動する場合</h4>



<p>[使用例]</p>



<p>子プロセス側：strlen-s.tcl</p>



<pre class="tcl">#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "$@"

# n 文字数
# s 文字列

set n [gets stdin s]
puts $n
</pre>



<p>親プロセス側：strlen-m.tcl</p>



<pre class="tcl">#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "$@"

puts "入力した文字列の文字数を表示します。"

while {1} {
    set fid [open "| tclsh strlen-s.tcl" "r+"]
    chan configure $fid -buffering line

    puts $fid [gets stdin]
    puts [gets $fid]
    close $fid

    puts -nonewline "終了？(y/n):"
    flush stdout

    if {[gets stdin] == y} {
        break
    }
}
</pre>



<p>[実行例]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">$ ./strlen-m.tcl
入力した文字列の文字数を表示します。
hello!
6
終了？(y/n):n
Good morning!
13
終了？(y/n):y
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>putsコマンドのデフォルトでは、標準出力へ出力する際に改行がくると自動でフラッシュします。よって上の例では子プロセス側はflushコマンドやchanコマンドは不要です。</p>



<p>上の例では、子プロセス側は文字数を返すとすぐに終了します。親プロセス側のループ内で子プロセスの起動をその都度行っています。</p>



<p>次の例は、文字数の出力後も子プロセスを継続して起動させた状態にした場合の例です。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">送受信後も子プロセスを継続して稼働させる場合</h4>



<p>[使用例]</p>



<p>子プロセス側：strlen-s2.tcl</p>



<pre class="tcl">#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "$@"

# n 文字数
# s 文字列

while {1} {
    set n [gets stdin s]
    puts $n
}
</pre>



<p>親プロセス側：strlen-m2.tcl</p>



<pre class="tcl">#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "$@"

puts "入力した文字列の文字数を表示します。"

set fid [open "| tclsh strlen-s2.tcl" "r+"]
chan configure $fid -buffering line

while {1} {
    puts $fid [gets stdin]
    puts [gets $fid]

    puts -nonewline "終了？(y/n):"
    flush stdout

    if {[gets stdin] == y} {
        break
    }
}
catch {close $fid}
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>この場合、親プロセス側の最後に記述しているcloseコマンドをcatchコマンドで捕捉するようにしないと、以下のエラーメッセージを表示して異常終了します。</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">error writing "stdout": broken pipe
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>closeコマンドのマニュアルに以下の説明が記載されています。</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>If channelId is a blocking channel for a command pipeline then close waits for the child processes to complete. </p><p>channelIdがコマンドパイプラインのブロッキングチャネルである場合、クローズは子プロセスが終了するのを待ちます。</p><cite><a rel="noopener" href="http://www.tcl.tk/man/tcl8.6/TclCmd/close.htm" target="_blank" aria-label="http://www.tcl.tk/man/tcl8.6/TclCmd/close.htm (新しいタブで開く)">http://www.tcl.tk/man/tcl8.6/TclCmd/close.htm</a></cite></blockquote>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>どうやらcloseコマンドでパイプラインを閉じる時は、子プロセスを終了させないとダメなようです。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">継続稼働中の子プロセスを終了させるには</h4>



<p>子プロセスを終了させる方法を２つ紹介します。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[使用例1]</p>



<p>子プロセス側：strlen-s3.tcl</p>



<pre class="tcl">#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "$@"

# n 文字数
# s 文字列

while {[set n [gets stdin s]] &gt; 0} {
    puts $n
}
</pre>



<p>親プロセス側：strlen-m3.tcl</p>



<pre class="tcl">#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "$@"

puts "入力した文字列の文字数を表示します。"

set fid [open "| tclsh strlen-s3.tcl" "r+"]
chan configure $fid -buffering line

while {1} {
    puts $fid [gets stdin]
    puts [gets $fid]

    puts -nonewline "終了？(y/n):"
    flush stdout

    if {[gets stdin] == y} {
        puts $fid ""    ;# 空行を送って子プロセスを終了させる。
        break
    }
}
close $fid
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>使用例1では、空の文字列(文字数0)を送ることで、子プロセスを終了するようにしてます。</p>



<p>空の文字列でなくても&#8221;quit&#8221;が来たら終了させるなど、子プロセスへ送る文字列のルールを決めることで終了させることができそうですよね。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>子プロセスを終了させる方法をもう１つ紹介します。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[使用例2]</p>



<p>子プロセス側はstrlen-s2.tclを使います。</p>



<p>親プロセス側：strlen-m4.tcl</p>



<pre class="tcl">#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "$@"

puts "入力した文字列の文字数を表示します。"

set fid [open "| tclsh strlen-s2.tcl" "r+"]
chan configure $fid -buffering line

while {1} {
    puts $fid [gets stdin]
    puts [gets $fid]

    puts -nonewline "終了？(y/n):"
    flush stdout

    if {[gets stdin] == y} {
        set pid [pid $fid] 
        exec kill $pid
        break
    }
}
catch {close $fid}
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>pidコマンドはopenコマンドで起動したプロセスのプロセスIDを返します。</p>



<p>例2では、OS標準のkillコマンドを使って子プロセスを終了させています。この場合もcloseコマンドをcatchコマンドで捕捉するようにしないと、以下のエラーメッセージを表示します。</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">child killed: software termination signal
    while executing
"close $fid"
    (file "./strlen-m4.tcl" line 23)
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>ネットで色々調べていると、クローズする時に、パイプラインプロセスの異常終了などにより、closeコマンドがエラーになることがあるので、catchコマンドを使うようにしたほうがいいようです。</p>



<p>参考：<a rel="noopener" href="https://www.tek-tips.com/viewthread.cfm?qid=438174" target="_blank" aria-label="killing process in tcl (新しいタブで開く)">killing process in tcl</a></p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>Windowsには、killコマンドがないので、Tclの標準機能だけで、この方法を使うことは出来ませんが、TclXという拡張ライブラリを使うと、拡張ライブラリのkillコマンドが使えます。</p>



<p>ActiveTclにインストールされていたので使用してみました。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[使用例2-2]</p>



<pre class="tcl">#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "$@"

package require Tclx    ;# Tclxを追加

puts "入力した文字列の文字数を表示します。"

set fid [open "| tclsh strlen-s2.tcl" "r+"]
chan configure $fid -buffering line

while {1} {
    puts $fid [gets stdin]
    puts [gets $fid]

    puts -nonewline "終了？(y/n):"
    flush stdout

    if {[gets stdin] == y} {
        set pid [pid $fid] 
        kill $pid    ;# Tclxのkillコマンド
        break
    }
}
catch {close $fid}
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>package require xxxx で拡張ライブラリが使えます。<br>packageコマンドについては別途紹介しようと思います。</p>



<p>参考：<br><a href="https://wiki.tcl-lang.org/page/kill">https://wiki.tcl-lang.org/page/kill</a><br><a href="https://wiki.tcl-lang.org/page/chan+pipe">https://wiki.tcl-lang.org/page/chan+pipe</a></p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Tcl &#8211; 外部プログラムの実行について -exec-</title>
		<link>https://blog.it-see.net/it-dokata/tcl-tk/exec/</link>
					<comments>https://blog.it-see.net/it-dokata/tcl-tk/exec/#comments</comments>
		
		<dc:creator><![CDATA[いっしー]]></dc:creator>
		<pubDate>Tue, 03 Dec 2019 07:24:08 +0000</pubDate>
				<category><![CDATA[Tcl/Tk]]></category>
		<guid isPermaLink="false">https://blog.it-see.net/it-dokata/?p=1373</guid>

					<description><![CDATA[目次 外部プログラムの実行execコマンドexecコマンドの使用例UNIXでの使用例Windowsでの使用例 外部プログラムの実行 Tclシェルを起動して対話的に実行する場合、未定義のTclコマンドが入力されると、外部プ [&#8230;]]]></description>
										<content:encoded><![CDATA[

  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-6" checked><label class="toc-title" for="toc-checkbox-6">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">外部プログラムの実行</a></li><li><a href="#toc2" tabindex="0">execコマンド</a></li><li><a href="#toc3" tabindex="0">execコマンドの使用例</a><ol><li><a href="#toc4" tabindex="0">UNIXでの使用例</a></li><li><a href="#toc5" tabindex="0">Windowsでの使用例</a></li></ol></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">外部プログラムの実行</span></h2>



<p>Tclシェルを起動して対話的に実行する場合、未定義のTclコマンドが入力されると、外部プログラムとして実行するように設定されています。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[使用例1]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">$ tclsh

# 外部コマンドのdateを実行
% date
2019年  2月 13日 水曜日 15:36:02 JST

# 予期せぬ動作
% set d &#91;date&#93;
2019年  2月 13日 水曜日 15:36:35 JST

% puts $d

%
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>1つ目の例は、OS標準コマンドのdateコマンドを実行して現在の日時を表示しています。</p>



<p>2つ目の例は、dateコマンドを実行して現在の日時を変数dに格納しようとして失敗しています。</p>



<p>Tclシェルを起動して通常のシェルと同じようにOS標準コマンドが実行できるのは便利であるのですが、色々試していると、2つ目の例のように予期せぬ振る舞いに遭遇することもあります。</p>



<p>外部プログラムの実行をさせないようにするには、変数auto_noexecを定義します。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[使用例2]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">$ tclsh
% set auto_noexec 1
1
% date
invalid command name "date"
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc2">execコマンド</span></h2>



<p>[書式]</p>



<pre class="nohighlight"><strong>exec</strong> ?<em>switches</em>? <em>arg</em> ?<em>arg ...</em>? ?<em>&amp;</em>?
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>execコマンドはサブプロセスを呼び出します。</p>



<p>Tclのスクリプトファイル内で外部プログラムを実行したり、実行した結果を利用するには、execコマンドを使います。Tclシェルを起動して対話的に実行する場合にも明示的にexecコマンドを実行することで、外部コマンドの出力結果を利用することができます。</p>



<p>[使用例1]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">$ tclsh
% set d [exec date]
2019年  2月 13日 水曜日 16:45:10 JST
% puts $d
2019年  2月 13日 水曜日 16:45:10 JST
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>execコマンドはパイプラインやリダイレクトもサポートしています。以下の例はlsコマンドの出力結果をパイプラインを使ってgrepコマンドに渡しています。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">$ tclsh

% set dir [exec ls | grep hello*]
hello-w.tcl
hello.tcl

% puts $dir
hello-w.tcl
hello.tcl
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>execコマンドのオプションや使用できるリダイレクションは以下のようなものがあります。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<table class="wp-block-table aligncenter"><tbody><tr><th>スイッチ</th><th>意味</th></tr><tr><td><strong> -ignorestderr</strong> </td><td>標準エラーチャネルへのメッセージ出力をエラーケースとして処理しないようにする。<br><br>※ 2&gt;@stderr と同じ？<br>サブプロセスのstderrをメインプロセスのstderrに戻す模様。<br><br>[参考]<br><a rel="noopener" aria-label="https://wiki.tcl-lang.org/page/exec (新しいタブで開く)" href="https://wiki.tcl-lang.org/page/exec" target="_blank">https://wiki.tcl-lang.org/page/exec</a><br><a rel="noopener" href="https://wiki.tcl-lang.org/page/open" target="_blank" aria-label="https://wiki.tcl-lang.org/page/open (新しいタブで開く)">https://wiki.tcl-lang.org/page/open</a></td></tr><tr><td><strong> -keepnewline</strong> </td><td>パイプラインの出力における末尾の改行を削除しません。</td></tr><tr><td style="text-align: center;"><strong>－－</strong></td><td>スイッチ(?<em>switches</em>?)の終わりを示します。これに続く引数は「-」で始まっていても最初の引数(arg)として扱われます。</td></tr></tbody></table>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<table class="wp-block-table aligncenter"><tbody><tr><th style="width: 30%;">リダイレクション</th><th>意味</th></tr><tr><td style="text-align: center;"><strong>|</strong></td><td>個々のコマンドを区切ります。「|」の前に記述したコマンドの標準出力は、次のコマンドの標準入力に渡されます。<br>※「|」記号はパイプ、パイプラインと読みます。</td></tr><tr><td style="text-align: center;"><strong>|&amp;</strong></td><td>個々のコマンドを区切ります。「|&amp;」の前に記述したコマンドの標準出力と標準エラーの両方が、次のコマンドの標準入力に渡されます。この形式のリダイレクションは、2&gt;や&gt;&amp;などの形式をオーバライドします。</td></tr><tr><td style="text-align: center;"><strong>&lt;</strong> <em>fileName</em></td><td>fileNameで指定したファイルを開いて最初のコマンドの標準入力に渡します。</td></tr><tr><td style="text-align: center;"><strong>&lt;@</strong> <em>fileId</em></td><td>fileIdで指定したファイル識別子から最初のコマンドの標準入力に渡します。fileIdはopenコマンドなどにより、事前に読み込み可能なモードで開かれていなければなりません。</td></tr><tr><td style="text-align: center;"><strong>&lt;&lt;</strong> <em>value</em></td><td>valueで指定した値を最初のコマンドの標準入力に渡します。</td></tr><tr><td style="text-align: center;"><strong>&gt;</strong> <em>fileName </em></td><td>最後のコマンドの標準出力をfileNameで指定したファイルに出力します。ファイルの内容は上書きされます。</td></tr><tr><td style="text-align: center;"><strong>2&gt;</strong><em> fileName</em></td><td>全てのコマンドからの標準エラーをfileNameで指定したファイルに出力します。ファイルの内容は上書きされます。</td></tr><tr><td style="text-align: center;"><strong>&gt;&amp;</strong> <em>fileName </em></td><td>最後のコマンドの標準出力と全てのコマンドからの標準エラーの両方をfileNameで指定したファイルに出力します。ファイルの内容は上書きされます。</td></tr><tr><td style="text-align: center;"><strong>&gt;&gt;</strong><em> fileName</em></td><td>最後のコマンドの標準出力をfileNameで指定したファイルに出力します。ファイルの内容は追加されます。</td></tr><tr><td style="text-align: center;"><strong>2&gt;&gt;</strong> <em>fileName</em></td><td>全てのコマンドからの標準エラーをfileNameで指定したファイルに出力します。ファイルの内容は追加されます。</td></tr><tr><td style="text-align: center;"><strong>&gt;&gt;&amp;</strong> <em>fileName</em></td><td>最後のコマンドの標準出力と全てのコマンドからの標準エラーの両方をfileNameで指定したファイルに出力します。ファイルの内容は追加されます。</td></tr><tr><td style="text-align: center;"><strong>&gt;@</strong> <em>fileId</em></td><td>最後のコマンドの標準出力をfileIdで指定したファイル識別子の出力チャネルに出力します。fileIdはopenコマンドなどにより、事前に書き込み可能なモードで開かれていなければなりません。</td></tr><tr><td style="text-align: center;"><strong>2&gt;@</strong> <em>fileId</em></td><td>全てのコマンドからの標準エラーをfileIdで指定したファイル識別子の出力チャネルに出力します。fileIdはopenコマンドなどにより、事前に書き込み可能なモードで開かれていなければなりません。</td></tr><tr><td style="text-align: center;"><strong>2&gt;@1</strong> </td><td>全てのコマンドからの標準エラーをコマンドの実行結果にリダイレクトします。この演算子はコマンドパイプラインの最後でのみ有効です。</td></tr><tr><td style="text-align: center;"><strong>&gt;&amp;@</strong><em> fileId</em></td><td>最後のコマンドの標準出力と全てのコマンドからの標準エラーの両方をfileIdで指定したファイル識別子の出力チャネルに出力します。fileIdはopenコマンドなどにより、事前に書き込み可能なモードで開かれていなければなりません。</td></tr></tbody></table>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<table class="wp-block-table aligncenter"><tbody><tr><td style="width: 18%;text-align: center;"><strong>&amp;</strong></td><td>最後の引数が「&amp;」の場合、パイプラインはバックグランドで実行されます。この場合、execコマンドは、パイプライン内の全てのサブプロセスのプロセス識別子をリストにしたもの返します。<br><br>パイプラインの最後のコマンドからの標準出力は、リダイレクトされていない場合はアプリケーションの標準出力に送られ、パイプラインのすべてのコマンドからのエラー出力はリダイレクトされない限りアプリケーションの標準エラーに送られます。</td></tr></tbody></table>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>標準出力がリダイレクトされていない場合、“ 2&gt; @ 1”が指定されていない限り、execコマンドはパイプラインの最後のコマンドから標準出力を返します。この場合、標準エラーも含まれます。 </p>



<p>もし、パイプライン内のいずれかのコマンドが異常終了したり、強制終了されたり中断されたりした場合、execはエラーを返します。エラーメッセージにはパイプラインの出力とそれに続く異常終了を説明するエラーメッセージが含まれます。 </p>



<p>グローバル変数のerrorcodeには、最後に発生した異常終了に関する追加情報が含まれます。 </p>



<p>もし、いずれかのコマンドが標準エラーに出力して、その標準エラーがリダイレクトされずに、-ignorestderrも指定されていない場合にはexecはエラーを返します。 エラーメッセージには、パイプラインの標準出力と、それに続いて異常終了に関するメッセージ（もしあれば）を出力し、その後に標準エラーが出力されます。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc3">execコマンドの使用例</span></h2>



<p>execコマンドの使用例をいくつか紹介します。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc4">UNIXでの使用例</span></h3>



<p>[使用例1]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">set n [exec cat str.txt | wc -l]
puts $n
=&gt; 8
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>使用例1は、catコマンドのファイル指定で読み込んで、wcコマンドで行数の取得。結果を変数nに代入しています。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[使用例2]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">(1) exec cat &lt; str.txt | wc -l &gt; str.line
(2) set fid [open str.line r]
    set line [exec cat &lt;@ $fid]
    =&gt; 8
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>(1)は、ファイル名で指定したファイルの内容を標準入力からcatコマンドに渡して、wcコマンドで行数の取得。結果をファイル：str.lineへ出力しています。</p>



<p>(2)は、str.lineを開いてファイル識別子を指定してcatコマンドに渡しています。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[使用例3]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">(1) exec date &gt; ping.txt
(2) set pid [exec ping -i 5 192.168.11.1 &gt;&gt;&amp; ping.txt &amp;]
(3) exec kill $pid
    exit
 
    $ cat ping.txt
    2019年  2月 21日 木曜日 16:00:48 JST
    PING 192.168.11.1 (192.168.11.1) 56(84) bytes of data.
    64 bytes from 192.168.11.1: icmp_seq=2 ttl=64 time=0.678 ms
    64 bytes from 192.168.11.1: icmp_seq=3 ttl=64 time=0.743 ms
    64 bytes from 192.168.11.1: icmp_seq=4 ttl=64 time=0.662 ms
    64 bytes from 192.168.11.1: icmp_seq=5 ttl=64 time=0.751 ms
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>(1)は、日付をping.txtに書き込みしています。</p>



<p>(2)は、pingコマンドをバックグランドで起動し、標準出力と標準エラーの両方をping.txtに追加書き込みするようにしています。</p>



<p>ping -i 5 は、相手先に5秒間隔でパケットを送信します。</p>



<p>末尾の「&amp;」がないとフォアグランドで子プロセス(pingコマンド)を起動するので、起動した子プロセスが終了するまで、Tcl(親プロセス側)で次のコマンドが実行できなくなります。その場合、Ctrl+Cなどでpingコマンドを強制終了する必要があります。</p>



<p>(2)のようにバックグランドで実行した場合、execコマンドの戻り値は、起動したpingコマンドのプロセスIDを返します。</p>



<p>(3)は、pingコマンドを終了させています。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc5">Windowsでの使用例</span></h3>



<p>[使用例1]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">(1) exec notepad &amp;
(2) exec c:/windows/system32/notepad.exe &amp;
(3) exec {*}[auto_execok notepad] &amp;
</pre>



<p>(1)(2)(3)は、いずれもメモ帳を起動します。</p>



<p>(1)は、notepad.exeがPATH環境変数内にあることを想定しています。</p>



<p>(2)は、プログラムへのパスを明示的に指定しています。</p>



<p>(3)は、auto_execokコマンドを使用している。</p>



<p>　　auto_execok cmd</p>



<p>auto_execokはTclライブラリのコマンドで、指定したコマンド(cmd)が実行可能ファイル(シェル組み込み含む)として存在するかどうか判別します。存在している場合は、execコマンドで実行可能ファイルを実行する為に引数リストをexecコマンドに渡します。存在しない場合は、空文字列を返します。</p>



<p>{*}の構文は、複数の引数に展開します。Tclはデフォルトで複数の引数に展開しないので、複数の引数が1つの文字列として扱われ、エラーになる可能性があります。{*}は8.5から使えるようになりました。それまでは、evalコマンドで以下のように記述していました。</p>



<p>　　eval exec [auto_execok notepad] &amp;</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>Windowsの場合、拡張子にプログラムの関連付けがされているので以下のような使い方もできます。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[使用例2]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">(1) exec {*}[auto_execok start] https://wiki.tcl-lang.org
(2) exec {*}[auto_execok start] hello-w.tcl &amp;
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>(1)は、ブラウザを起動してTcler&#8217;s Wiki!のページを表示します。</p>



<p>(2)は、hello-w.tclのプログラムを起動します。</p>



<p>{*}やevalコマンドを使わなかった場合、以下のエラーになります。</p>



<pre class="nohighlight">couldn't execute "C:\Windows\System32\cmd.exe \c start": no such file or directory
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>evalコマンドと{*}構文は「<a href="https://blog.it-see.net/it-dokata/tcl-tk/eval/" target="_blank" aria-label="Tcl - evalコマンドと{*}構文について (新しいタブで開く)">Tcl &#8211; evalコマンドと{*}構文について</a>」で紹介しています。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.it-see.net/it-dokata/tcl-tk/exec/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Tcl &#8211; evalコマンドと{*}構文について</title>
		<link>https://blog.it-see.net/it-dokata/tcl-tk/eval/</link>
		
		<dc:creator><![CDATA[いっしー]]></dc:creator>
		<pubDate>Tue, 03 Dec 2019 07:22:53 +0000</pubDate>
				<category><![CDATA[Tcl/Tk]]></category>
		<guid isPermaLink="false">https://blog.it-see.net/it-dokata/?p=1371</guid>

					<description><![CDATA[目次 evalコマンド{*}構文について evalコマンド [書式] eval arg ?arg ...? evalコマンドの引数はTclコマンドを１つ以上含むTclスクリプトを構成した引数をとります。 evalコマンド [&#8230;]]]></description>
										<content:encoded><![CDATA[

  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-8" checked><label class="toc-title" for="toc-checkbox-8">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">evalコマンド</a></li><li><a href="#toc2" tabindex="0">{*}構文について</a></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">evalコマンド</span></h2>



<p>[書式]</p>



<pre class="nohighlight"><strong>eval</strong> <em>arg</em> ?<em>arg ...</em>?
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><strong>eval</strong>コマンドの引数はTclコマンドを１つ以上含むTclスクリプトを構成した引数をとります。</p>



<p><strong>eval</strong>コマンドは<a href="https://blog.it-see.net/it-dokata/tcl-tk/list-1/#toc5" target="_blank" aria-label="concatコマンド (新しいタブで開く)">concatコマンド</a>と同じ方法で引数を展開します。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[使用例1]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">set a 10
set b {20 30 40}
set c 50

list $a $b $c
⇒ 10 {20 30 40} 50

concat $a $b $c
⇒ 10 20 30 40 50

eval list $a $b $c
⇒ 10 20 30 40 50
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>listコマンドでは$bを１つの値として展開します。</p>



<p>これをevalコマンドの引数で指定すると$bを３つの値として展開します。</p>



<p>Tclインタプリタは基本的に展開したものをさらに展開することはしませんが、evalコマンドを使うと展開した値をさらに展開することができます。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[使用例2]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">set script {
    puts "hello! hello!"
    puts "Good morning!"
}

eval $script
⇒ hello! hello!
   Good morning!
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>上の例では変数scriptを展開した文字列をTclコマンドとして再評価しています。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[使用例3]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">set prog "wish hello-w.tcl"

eval exec $prog &amp;
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>execコマンドは外部プログラムを実行します。</p>



<p>上の例では「wish hello-w.tcl」を「wish」と「hello-w.tcl」の２つの値として展開しています。</p>



<p>execコマンドについては「<a href="https://blog.it-see.net/it-dokata/tcl-tk/exec/" target="_blank" aria-label="外部プログラムの実行について (新しいタブで開く)">外部プログラムの実行について</a>」で説明します。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc2">{*}構文について</span></h2>



<p><strong>{*}</strong>の構文は、concatコマンドと同じ方法でリストを複数の引数として展開します。</p>



<p>{*}は8.5から使えるようになりました。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[使用例1]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">set a 10
set b {20 30 40}
set c 50

list $a $b $c
⇒ 10 {20 30 40} 50

eval list $a $b $c
⇒ 10 20 30 40 50

list $a {*}$b $c
⇒ 10 20 30 40 50
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>複数の引数をまとめた変数を展開する場合など、単なる文字列のリストを展開するだけであれば、evalコマンドよりも「{*}」を使用した方がシンプルで見やすいです。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[使用例2]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">set prog "wish hello-w.tcl"

exec {*}$prog &amp;
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>{*}構文を使った例は「<a href="https://blog.it-see.net/it-dokata/tcl-tk/exec/#toc5" target="_blank" aria-label="外部プログラムの実行について Windowsでの使用例 (新しいタブで開く)">外部プログラムの実行について Windowsでの使用例</a>」でも紹介しています。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Tcl &#8211; バイナリデータの操作(3) -binary scan-</title>
		<link>https://blog.it-see.net/it-dokata/tcl-tk/binary-operetion3/</link>
		
		<dc:creator><![CDATA[いっしー]]></dc:creator>
		<pubDate>Thu, 07 Nov 2019 09:14:37 +0000</pubDate>
				<category><![CDATA[Tcl/Tk]]></category>
		<guid isPermaLink="false">https://blog.it-see.net/it-dokata/?p=1337</guid>

					<description><![CDATA[目次 binary scan16進ダンプ binary scan [書式] binary scan string formatString ?varName varName ...? binary scanは、forma [&#8230;]]]></description>
										<content:encoded><![CDATA[

  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-10" checked><label class="toc-title" for="toc-checkbox-10">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">binary scan</a></li><li><a href="#toc2" tabindex="0">16進ダンプ</a></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">binary scan</span></h2>



<p>[書式]</p>



<pre class="nohighlight"><strong>binary scan</strong> <em>string formatString</em> ?<em>varName varName ...</em>?
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><strong>binary scan</strong>は、<em>formatString</em>で指定した書式に従って<em>string</em>で指定したバイナリデータを文字列に変換を行い、変換した文字列を<em>varName</em>へ格納します。戻り値は変換した個数を返します。</p>



<p><em>string</em>は、1文字につき1バイト、<span class="marker-under">1バイトとして表現できない文字の上位ビットは切り捨てられます。</span></p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><strong><span class="marker-under-red">formatStringの指定方法</span></strong></p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">set bin [binary format a* abcdefghi]
=&gt; abcdefghi 相当のバイナリ値が変数binに格納されます。

binary scan $bin HH2H4H6H* n1 n2 n3 n4 n5
=&gt; 5 変換した個数を返します。

puts "$n1 $n2 $n3 $n4 $n5"
=&gt; 6 62 6364 656667 6869
      b  c d  e f g  h i
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>フィールドは、H, H2, H4, H6 H* の5つあります。変換した値を格納する<em>varName</em>もフィールドの個数だけ必要になります。</p>



<p>フィールドの最初の単一文字は変換方法を示すタイプで、その後に続く数字は変換を繰り返す回数(count)を表します。数字の代わりに&#8221;*&#8221;を使うと、対応するargの文字列すべて変換します。</p>



<p>タイプ&#8221;H&#8221;は、変数binのバイナリデータをバイト内で、上位から下位の順番で16進数表記の文字列に変換します。countを省略すると、1桁だけ変換されます。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>タイプに指定できる種類は以下のようなものがあります。</p>



<hr class="wp-block-separator is-style-default"/>



<p><span class="fz-24px"><strong>a</strong></span><br>バイナリデータを文字列に変換します。</p>



<p>全てのバイトは、\u0000-\u00ffの範囲の文字として解釈される為、stringで指定したデータが、バイナリ文字列であっても、ISO 8859-1でエンコードされた文字列でもない場合は、encoding convertfromコマンドが必要になります。</p>



<p>例1.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary scan \x48\x65\x6c\x6c\x6f\x21 a* str1
=&gt; 1
puts $str1
=&gt; Hello!
</pre>



<p>例2.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary scan \xe3\x83\x90\xe3\x82\xa4\xe3\x83\x90\xe3\x82\xa4 a* str1
=&gt; 1
puts $str1
=&gt; 文字化けする。
puts [encoding convertfrom utf-8 $str1]
=&gt; バイバイ
</pre>



<p>[参考]<br>＊ISO 8859-1(Latin-1)<br>ASCII文字コードに西ヨーロッパ諸国で使われるラテン文字を追加した文字集合。<br><a href="https://ja.wikipedia.org/wiki/ISO/IEC_8859-1">https://ja.wikipedia.org/wiki/ISO/IEC_8859-1</a><br><a rel="noopener" aria-label="http://e-words.jp/w/ISO-IEC_8859.html (新しいタブで開く)" href="https://ja.wikipedia.org/wiki/ISO/IEC_8859-1" target="_blank">http://e-words.jp/w/ISO-IEC_8859.html</a></p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>A</strong></span><br><strong>a</strong>と同じですが、末尾の空白とNULLが変数に格納される前に削除されます。</p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary scan "\x61\x62\x63\x20\x64\x65  \x66  \x00" A* var1
=&gt; 1
puts $var1
=&gt; abc de  f 末尾の空白とNULL(\x00)は削除されます。
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>b</strong></span><br>バイナリデータをlow-to-high順で2進数表記の文字列に変換します。</p>



<p>stringで指定したバイナリデータはバイト単位でfirst-to-lastの順番でスキャンされ、バイト内のビットはlow-to-high順でcountビット分、2進数表記の文字列で出力します。 countが*の場合、stringの残りのすべてのビットがスキャンされます。 countが省略された場合、1ビットがスキャンされます。</p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary scan \x07\x87\x05 b5b* var1 var2
=&gt; 2
puts $var1
=&gt; 11100
puts $var2
=&gt; 1110000110100000
</pre>



<p>[参考]</p>



<pre class="nohighlight">     0x07        0x87       0x05
  0000 0111  10000 0111  0000 0101
    -------  ---------------------
      ↓               ↓
     var1             var2
</pre>



<p><strong>var1</strong><br>low-to-high順で5ビット分格納される。<br><strong>var2</strong><br>0x87,0x05の順でスキャンされ、バイト内のビットは、low-to-high順でvar2に格納される。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>B</strong></span><br>bと同じですが、各バイト内のビットを、high-to-lowの順で2進数表記の文字列で出力します。</p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary scan \x70\x87\x05 B5B* var1 var2
=&gt;2
puts $var1
=&gt; 01110
puts $var2
=&gt;1000011100000101
</pre>



<p>[参考]</p>



<pre class="nohighlight">     0x70        0x87       0x05
  0111 000  10000 0111  0000 0101
  ------    ---------------------
    ↓                ↓
   var1              var2
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>h</strong></span><br>バイナリデータをlow-to-high順で16進数表記の文字列に変換します。</p>



<p>stringで指定したバイナリデータはバイト単位でfirst-to-lastの順番でスキャンされ、バイト内のデータはlow-to-high順で16進数表記の文字列で出力します。 countが*の場合、stringの残りのすべてのデータがスキャンされます。 countが省略された場合、1桁(4bit)がスキャンされます。</p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary scan \x07\x86\x05\x12\x34 h3h* var1 var2
=&gt; 2
puts $var1
=&gt; 706
puts $var2
=&gt; 502143
</pre>



<p>[参考]</p>



<pre class="nohighlight">    0x07       0x86       0x05       0x12       0x34
  0000 0111  1000 0110  0000 0101  0001 0010  0011 0100
  ---- ----       ----  ---- ----  ---- ----  ---- ----
    0    7          6     0    5     1    2     3    4
    ------------------   ------------------------------
             ↓                         ↓
　　　　var1 =&gt; 706　　　　　　　  var2 =&gt; 502143
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>H</strong></span><br>hと同じですが、各バイト内のデータを、high-to-lowの順で16進数表記の文字列で出力します。</p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary scan \x07\xC6\x05\x1f\x34 H3H* var1 var2
=&gt; 2
puts $var1
=&gt; 07c
puts $var2
=&gt;051f34
</pre>



<p>[参考]</p>



<pre class="nohighlight">    0x07       0xc6       0x05       0x1f       0x34
  0000 0111  1100 0110  0000 0101  0001 1111  0011 0100
  ---- ----  ----       ---- ----  ---- ----  ---- ----
    0    7     c          0    5     1    f     3    4
   --------------        ------------------------------
          ↓　                           ↓
　　　var1 =&gt; 07c                   var2 =&gt; 051f34
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>c</strong></span><br>バイナリデータを8ビット符号付き整数に変換します。変換したデータはリストとして対応する変数に格納されます。</p>



<p>countが*の場合、バイナリデータの残りすべてのバイトがスキャンされます。countが省略された場合、1つの8ビット整数がスキャンされます。</p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary scan \x07\x86\x05 c2c* var1 var2
=&gt; 2
puts $var1
=&gt; 7 -122
puts $var2
=&gt;5
</pre>



<p>変換したデータは符号付きの整数値ですが、以下のような式を使用して符号なし8ビット整数に変換できます。</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">expr {-122 &amp; 0xff}
=&gt; 134 は16進数で0x86です。
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>s</strong></span><br>バイナリデータをリトルエンディアン（little-endian）のバイト順で表される16ビット符号付き整数に変換します。変換したデータはリストとして対応する変数に格納されます。</p>



<p>countが*の場合、バイナリデータの残りすべてのバイトがスキャンされます。countが省略された場合、1つの16ビット整数がスキャンされます。</p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary scan \x05\x00\x07\x00\xf0\xff s2s* var1 var2
=&gt; 2
puts $var1
=&gt; 5 7
puts $var2
=&gt; -16
</pre>



<p>変換したデータは符号付きの整数値ですが、以下のような式を使用して符号なし16ビット整数に変換できます。</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">expr {-16 &amp; 0xffff}
=&gt; 65520 は16進数で0xfff0です。
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><span class="fz-24px"><strong>S</strong></span><br>バイナリデータをビッグエンディアン（big-endian）のバイト順で表される16ビット符号付き整数に変換します。それ以外は、<strong>s</strong>と同じです。</p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary scan \x00\x05\x00\x07\xff\xf0 S2S* var1 var2
=&gt; 2
puts $var1
=&gt; 5 7
puts $var2
=&gt; -16
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>t</strong></span><br>バイナリデータをTclスクリプトが実行されているマシンのネイティブのバイト順で表されるで16ビット符号付き整数として解釈されます。それ以外の点は、<strong>s</strong>および<strong>S</strong>と同じです。 マシンのネイティブのバイト順が何であるかを判断するには、tcl_platform配列のbyteOrder要素を参照してください。</p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">puts $tcl_platform(byteOrder)
=&gt; littleEndian
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>i</strong></span><br>バイナリデータをリトルエンディアン（little-endian）のバイト順で表される32ビット符号付き整数に変換します。変換したデータはリストとして対応する変数に格納されます。</p>



<p>countが*の場合、バイナリデータの残りすべてのバイトがスキャンされます。countが省略された場合、1つの32ビット整数がスキャンされます。</p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">set str \x05\x00\x00\x00\x07\x00\x00\x00\xf0\xff\xff\xff
=&gt; ðÿÿÿ
binary scan $str i2i* var1 var2
=&gt; 2
puts $var1
=&gt; 5 7
puts $var2
=&gt; -16
</pre>



<p>変換したデータは符号付きの整数値ですが、以下のような式を使用して符号なし16ビット整数に変換できます。</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">  expr {-16 &amp; 0xffffffff}
  =&gt; 4294967280 は16進数で0xfffffff0です。
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>I</strong></span><br>バイナリデータをビッグエンディアン（big-endian）のバイト順で表される32ビット符号付き整数に変換します。それ以外は、<strong>i</strong>と同じです。</p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">set str \x00\x00\x00\x05\x00\x00\x00\x07\xff\xff\xff\xf0
=&gt; ÿÿÿð
binary scan $str I2I* var1 var2
=&gt; 2
puts $var1
=&gt; 5 7
puts $var2
=&gt; -16
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>n</strong></span><br>バイナリデータをTclスクリプトが実行されているマシンのネイティブのバイト順で表されるで32ビット符号付き整数として解釈されます。それ以外の点は、<strong>i</strong>および<strong>I</strong>と同じです。 マシンのネイティブのバイト順が何であるかを判断するには、tcl_platform配列のbyteOrder要素を参照してください。</p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">puts $tcl_platform(byteOrder)
=&gt; littleEndian
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>w</strong></span><br>バイナリデータをリトルエンディアン（little-endian）のバイト順で表される64ビット符号付き整数に変換します。変換したデータはリストとして対応する変数に格納されます。</p>



<p>countが*の場合、バイナリデータの残りすべてのバイトがスキャンされます。countが省略された場合、1つの64ビット整数がスキャンされます。</p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">set str \x05\x00\x00\x00\x07\x00\x00\x00\xf0\xff\xff\xff
=&gt; ðÿÿÿ
binary scan $str wi* var1 var2
=&gt; 2
puts $var1
=&gt; 30064771077
puts $var2
=&gt; -16
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>W</strong></span><br>バイナリデータをビッグエンディアン（big-endian）のバイト順で表される64ビット符号付き整数に変換します。それ以外は、<strong>w</strong>と同じです。</p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">set str \x00\x00\x00\x05\x00\x00\x00\x07\xff\xff\xff\xf0
=&gt; ÿÿÿð
binary scan $str WI* var1 var2
=&gt; 2
puts $var1
=&gt; 21474836487
puts $var2
=&gt; -16
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>m</strong></span><br>バイナリデータをTclスクリプトが実行されているマシンのネイティブのバイト順で表されるで64ビット符号付き整数として解釈されます。それ以外の点は、<strong>w</strong>および<strong>W</strong>と同じです。 マシンのネイティブのバイト順が何であるかを判断するには、tcl_platform配列のbyteOrder要素を参照してください。</p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">puts $tcl_platform(byteOrder)
=&gt; littleEndian
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>f</strong></span><br>バイナリデータをマシンのネイティブ表現における単精度浮動小数点数として解釈されます。浮動小数点数は対応する変数にリストとして格納されます。</p>



<p>countが*の場合、バイナリデータの残りすべてのバイトがスキャンされます。countが省略された場合、1つの単精度浮動小数点数がスキャンされます。</p>



<p>浮動小数点数のサイズはアーキテクチャによって異なりますので、スキャンされるバイト数は異なります。 データが有効な浮動小数点数を表していない場合、結果の値は未定義でコンパイラに依存します。</p>



<p>たとえば、Intel(R) Core(TM) i7-4770 CPU上で実行されているWindowsシステムでは、</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary scan \xcd\xcc\xcc\x3f f var1
=&gt; 1
puts $var1
=&gt; 1.600000023841858 を返します。
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>r</strong></span><br>バイナリデータを単精度浮動小数点数としてリトルエンディアン（little-endian）順に解釈されることを除いて<strong>f</strong>と同じです。</p>



<p>この変換は、IEEE浮動小数点表現を使用しないシステムに移植することはできません。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>R</strong></span><br>バイナリデータを単精度浮動小数点数としてビッグエンディアン（big-endian）順に解釈されることを除いて<strong>f</strong>と同じです。</p>



<p>この変換は、IEEE浮動小数点表現を使用しないシステムに移植することはできません。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>d</strong></span><br>バイナリデータを倍精度浮動小数点数として解釈されることを除いて<strong>f</strong>と同じです。</p>



<p>たとえば、Intel(R) Core(TM) i7-4770 CPU上で実行されているWindowsシステムでは、</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f d var1
=&gt; 1
puts $var1
=&gt; 1.6 を返します。
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>q</strong></span><br>バイナリデータを倍精度浮動小数点数としてリトルエンディアン（little-endian）順に解釈されることを除いて<strong>d</strong>と同じです。</p>



<p>この変換は、IEEE浮動小数点表現を使用しないシステムに移植することはできません。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>Q</strong></span><br>バイナリデータを倍精度浮動小数点数としてビッグエンディアン（big-endian）順に解釈されることを除いて<strong>d</strong>と同じです。</p>



<p>この変換は、IEEE浮動小数点表現を使用しないシステムに移植することはできません。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>x</strong></span><br>指定したバイトデータのカーソル位置をcountバイトだけ進めます。countが*または現在のカーソル位置の後のバイト数より大きい場合、カーソルはバイトデータの最後のバイトの後に配置されます。countが省略された場合、カーソルは1バイト進められます。</p>



<p>この型は引数を消費しないことに注意してください。例えば、</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary scan \x01\x02\x03\x04 x2H* var1
=&gt; 1
puts $var1
=&gt; 0304 がvar1に格納されます。
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>X</strong></span><br>指定したバイトデータのカーソル位置をcountバイトだけ後ろに移動します。countが*または現在のカーソル位置よりも大きい場合、カーソルは位置0に配置されるので、次にスキャンされるバイトは文字列の最初のバイトになります。 countが省略された場合、カーソルは1バイト戻ります。 </p>



<p>この型は引数を消費しないことに注意してください。 例えば、</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary scan \x01\x02\x03\x04 c2XH* var1 var2
=&gt; 2
puts $var1
=&gt; 1 2 がvar1に格納されます。
puts $var2
=&gt; 020304 がvar2に格納されます。
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>@</strong></span><br>stringで指定されたバイナリデータ内のカーソル位置をcountで指定した絶対位置に移動する。位置0はstringの最初のバイトを表します。countが文字列の末尾を超えた位置を指す場合、カーソルは最後のバイトの後に配置されます。 countを省略すると、エラーが発生します。 </p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary scan \x01\x02\x03\x04 c2@1H* var1 var2
=&gt; 2
puts $var1
=&gt; 1 2
puts $var2
=&gt; 020304
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc2">16進ダンプ</span></h2>



<p>以下のプログラムは、binary scanを使用した、16進ダンプのプログラムです。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[サンプル] hexdump.tcl</p>



<pre class="tcl">
#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "$@"

# 16進ダンプ

proc hexdump {fname} {
    set addr 0    ;# アドレス
    set fid [open $fname {RDONLY BINARY}]
    while {![eof $fid]} {
        set str ""    ;# 16バイト毎に初期化
        for {set i 0} {$i < 16} {incr i} {
            set byte [read $fid 1]
            if {![eof $fid]} {
                binary scan $byte H* hex
                lappend str $hex
            } else {
                break    ;# forループから抜ける
            }
        }
        puts [format "%06X  %s" $addr $str]
        incr addr 16
    }
    close $fid
}

# main
set fname [lindex $argv 0]    ;# ファイル名の取得
hexdump $fname
</pre>



<p>[実行例]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">$ ./hexdump.tcl str.txt
000000  48 65 6c 6c 6f 21 20 48 65 6c 6c 6f 21 0a 47 6f
000010  6f 64 20 6d 6f 72 6e 69 6e 67 21 0a 42 79 65 20
000020  62 79 65 21 0a 48 61 76 65 20 61 20 6e 69 63 65
000030  20 64 61 79 21 0a e3 81 93 e3 82 93 e3 81 ab e3
000040  81 a1 e3 82 8f 0a e3 81 8a e3 81 af e3 82 88 e3
000050  81 86 e3 81 94 e3 81 96 e3 81 84 e3 81 be e3 81
000060  99 e3 80 82 0a e3 83 90 e3 82 a4 e3 83 90 e3 82
000070  a4 0a e3 82 88 e3 81 84 31 e6 97 a5 e3 82 92 ef
000080  bc 81 0a
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>文字列操作など、色々説明していない事があるので、単純に１バイトずつ読み込んで16進表記で表示するようにしました。</p>



<p>16バイトずつ読み込んでから、文字列を整形したほうが効率がいいと思います。</p>



<p>[参考]<br><a rel="noopener" aria-label="Dump a file in hex and ASCII (新しいタブで開く)" href="https://wiki.tcl-lang.org/page/Dump+a+file+in+hex+and+ASCII" target="_blank">Dump a file in hex and ASCII</a></p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator"/>



<div class="blogcard-shortcode-wrap paragraph">binary formatコマンドの使い方については以下の記事で紹介しています。<br><a href="https://blog.it-see.net/it-dokata/tcl-tk/binary-operetion2/" title="Tcl - バイナリデータの操作(2) -binary format-" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="160" height="107" src="https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/05/アイコン7-160x107.jpg" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/05/アイコン7-160x107.jpg 160w, https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/05/アイコン7-300x200.jpg 300w, https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/05/アイコン7-120x80.jpg 120w, https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/05/アイコン7-320x213.jpg 320w, https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/05/アイコン7.jpg 480w" sizes="(max-width: 160px) 100vw, 160px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">Tcl - バイナリデータの操作(2) -binary format-</div><div class="blogcard-snippet internal-blogcard-snippet">Tclでバイナリデータを取り扱うにはbinaryコマンドを使います。この記事ではbinary formatの引数 formatString に指定できる値と使い方について紹介します。</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://blog.it-see.net/it-dokata" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">blog.it-see.net</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2019.10.31</div></div></div></div></a></div>



<div class="blogcard-shortcode-wrap paragraph">バイナリデータの基本的な操作につては以下の記事で紹介しています。<br><a href="https://blog.it-see.net/it-dokata/tcl-tk/binary-operetion/" title="Tcl - バイナリデータの操作(1)" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="160" height="107" src="https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/05/アイコン7-160x107.jpg" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/05/アイコン7-160x107.jpg 160w, https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/05/アイコン7-300x200.jpg 300w, https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/05/アイコン7-120x80.jpg 120w, https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/05/アイコン7-320x213.jpg 320w, https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/05/アイコン7.jpg 480w" sizes="(max-width: 160px) 100vw, 160px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">Tcl - バイナリデータの操作(1)</div><div class="blogcard-snippet internal-blogcard-snippet">Tclでバイナリデータを取り扱うにはbinaryコマンドを使います。binaryコマンドの操作を３回に分けて紹介します。この記事ではバイナリデータを読み書きする時の基本的な操作を紹介します。</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://blog.it-see.net/it-dokata" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">blog.it-see.net</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2019.10.29</div></div></div></div></a></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Tcl &#8211; バイナリデータの操作(2) -binary format-</title>
		<link>https://blog.it-see.net/it-dokata/tcl-tk/binary-operetion2/</link>
		
		<dc:creator><![CDATA[いっしー]]></dc:creator>
		<pubDate>Thu, 31 Oct 2019 08:55:03 +0000</pubDate>
				<category><![CDATA[Tcl/Tk]]></category>
		<guid isPermaLink="false">https://blog.it-see.net/it-dokata/?p=1311</guid>

					<description><![CDATA[binary format [書式] binary format formatString ?arg arg ...? binary formatは、formatString で指定した書式に従って arg で指定した文 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">binary format</h2>



<p>[書式]</p>



<pre class="nohighlight"><strong>binary format</strong> <em>formatString</em> ?<em>arg arg ...</em>?
</pre>



<p><strong>binary format</strong>は、<em>formatString</em> で指定した書式に従って <em>arg</em> で指定した文字列をバイナリデータに変換を行い、変換したバイナリデータを返します。</p>



<p><em><strong><span class="marker-under-red">formatString</span></strong></em><strong><span class="marker-under-red">の指定方法</span></strong></p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary fomat a3a2  Good morning!
=&gt; Goomo
</pre>



<p> f<em>ormatString</em> のフィールドは&#8221;a3&#8243;と&#8221;a2&#8243;の２つあります。それに対応する値も&#8221;Good&#8221;と&#8221;morning!&#8221;の２つあります</p>



<p>フィールドの最初の単一文字は変換方法を示すタイプです。その後に続く数字は変換を繰り返す回数(count)を表します。数字の代わりに&#8221;*&#8221;を使うと、対応する<em>arg</em>の文字列すべて変換します。</p>



<p>タイプ&#8221;a&#8221;は、文字列<em>age</em>のcount桁数のバイト列(バイナリデータ)に変換して返します。例の場合は、Gooの３文字とmoの２文字をバイト列にしたものが返されます。</p>



<p>Goomoの文字を16進数で表現すると以下のようになります。</p>



<pre class="nohighlight">47 6f 6f 6d 6f
G  o  o  m  o
</pre>



<p>よって、\x47\x6f\x6f\x6d\x6f に相当するバイナリ値を返します。</p>



<p>例では、アスキコードの範囲内の文字なので、変換後も文字として見えていますが、漢字などアスキコードの範囲外の文字であれば、返されたバイナリデータは文字化けします。</p>



<div class="wp-block-cocoon-blocks-label-box-1 label-box lb-cyan block-box"><div class="label-box-label block-box-label fab-pencil"><span class="label-box-label-text block-box-label-text">メモ</span></div><div class="label-box-content">
<p>例の結果を見ると、一見、文字から文字へ変換しているように見えますが、文字データからバイナリデータに変換しています。</p>
</div></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>タイプに指定できる種類は以下のようなものがあります。</p>



<hr class="wp-block-separator is-style-default"/>



<p><strong><span class="fz-24px">a</span></strong><br>文字列<em>arg</em>をcount桁分、バイナリ値で出力します。</p>



<p><em>arg</em>がcountより少ない場合、00で埋められます。countより多い場合は、切り捨てられます。countを省略した場合、１文字が変換されます。countが&#8221;*&#8221;の場合、全て変換されます。</p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary format a8  Hello!
=&gt; Hello!
</pre>



<p>\x48\x65\x6c\x6c\x6f\x21\x00\x00 に相当するバイナリ値を返します。</p>



<pre class="nohighlight">\x48\x65\x6c\x6c\x6f\x21\x00\x00
  H   e   l   l   o   !  
</pre>



<p>※日本語を扱う場合、「<a href="https://blog.it-see.net/it-dokata/tcl-tk/binary-operetion2/2/" target="_blank" aria-label="binaryコマンドの日本語の扱いについて (新しいタブで開く)">binaryコマンドの日本語の扱いについて</a>」を参照してください。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><strong><span class="fz-24px">A</span></strong><br><em>arg</em>がcountより少ない場合、スペースで埋められます。それ以外は、<strong>a</strong>と同じ。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary format a8  Hello!
=&gt; Hello!
</pre>



<p>\x48\x65\x6c\x6c\x6f\x21\x20\x20 に相当するバイナリ値を返します。</p>



<pre class="nohighlight">\x48\x65\x6c\x6c\x6f\x21\x20\x20
  H   e   l   l   o   !  空白 空白
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>b</strong></span><br>２進数表記の文字列(<em>age</em>)をcount桁分、バイト単位でlow-to-high順に出力します。</p>



<p><em>arg</em>は文字&#8221;1&#8243;と&#8221;0&#8243;で指定します。<em>arg</em>がcountより少ない場合、残りのビットは、ゼロで埋められます。countより多い場合は、切り捨てられます。countを省略した場合、１ビットが出力されます。countが&#8221;*&#8221;の場合、全て出力されます。出力されたビット数がバイト境界で終了しない場合、残りのビットはゼロで埋められます。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary format b8b* 110010 011100110101
=&gt; \x13\xce\x0a に相当するバイナリ値を返します。
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[参考]<br>・<strong>ビット・桁の数え方</strong></p>



<pre class="nohighlight">　　　　　　上位 下位
            7654 3210 ←bit ※計算機により異なります。
　　8桁目→ 1111 1110 ←1桁目
　　　　　　　F    E
</pre>



<p>・<strong>例の場合</strong></p>



<pre class="nohighlight">　|-------|  |-------| |-------| ← バイト境界
　1100 10<span class="red-under">00</span>  0111 0011 0101 <span class="red-under">0000</span> ←  2進数
    C    8     7    3    5    0  ← 16進数
</pre>



<p><span class="marker-under">バイト内でlow-to-high順なので通常とは逆に数えます。</span></p>



<pre class="nohighlight">　<span class="red-under">00</span>01 0011  1100 1110  <span class="red-under">0000</span> 1010 ←  2進数
    1    3     C    E    0    A   ← 16進数
</pre>



<p><span class="red">赤線</span>：不足分を0で埋められています。</p>



<p>※最上位ビット(MSB)を0とするか最下位ビット(LSB)を0とするかは計算機により違います。<br>最上位ビット<br><a href="https://ja.wikipedia.org/wiki/最上位ビット">https://ja.wikipedia.org/wiki/最上位ビット</a><br>エンディアン<br><a href="https://ja.wikipedia.org/wiki/エンディアン">https://ja.wikipedia.org/wiki/エンディアン</a></p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>B</strong></span><br>ビットが各バイト内のhigh-to-lowの順番で出力されることを除いて、<strong>b</strong>と同じです。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary format B8B* 110010 011100110101
=&gt; \xc8\x73\x50 に相当するバイナリ値を返します。
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>h</strong></span><br>16進数表記の文字列(<em>age</em>)をcount桁分、バイト単位でlow-to-high順に出力します。</p>



<p><em>arg</em>は文字「0123456789abcdefABCDEF」で指定します。<br>変換されるバイナリ値は、<em>arg</em>で指定した16進数表記の文字2つからバイト値を求め、バイト内で下位から上位(low-to-high)の順で出力されます。</p>



<p><br><em>arg</em>の桁数がcountより少ない場合は、残りの桁にゼロが使用されます。<em>arg</em>が指定された桁数より多い場合、余分な桁は無視されます。countが*の場合、<em>arg</em>内のすべての数字が変換されます。</p>



<p><br>変換された桁数がバイト境界で終了しない場合、残りの4ビットはゼロになります。countが省略された場合、1桁が変換されます。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>例1.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary format h3h* AB def
=&gt; \xba\x00\xed\x0f に相当するバイナリ値を返します。
</pre>



<p>例2.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary format h AB
=&gt; \x0a に相当するバイナリ値を返します。

</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[参考]</p>



<p>例1</p>



<pre class="nohighlight">上位 下位　　
1010 1011    　　→ 下位・上位順の為、BAのバイナリ値が出力される。
 A    B        　　countが3かつバイト境界でない為、残りの桁が00になる。

上位 下位 上位
1101 1110 1111　→ 下位・上位順の為、edのバイナリ値が出力される。
 d    e    f　　　最後の桁は、バイト境界でないので、f0になり、
　　　　　　　　　　 下位・上位順の為、0fのバイナリ値が出力される。
</pre>



<p>例2.</p>



<p>countが省略されている為、1桁の&#8221;A&#8221;のみ変換され、残りの桁&#8221;B&#8221;の4ビットは変換されずにゼロになります。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>H</strong></span><br>バイト内で上位から下位(high-to-low)の順で出力されることを除いて、<strong>h</strong>と同じです。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>例.1</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary format h3h* AB def
=&gt; \xab\x00\xde\xf0 に相当するバイナリ値を返します。
</pre>



<p>例2.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary format h AB
=&gt; \xa0 に相当するバイナリ値を返します。
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>c</strong></span><br>1つ以上の8ビット整数値を変換します。</p>



<p><em>arg</em>は整数値で指定します。countが指定されていない場合、<em>arg</em>は１つの整数値でなければなりません。countが指定されている場合、<em>arg</em>は、その数のリストで指定します。各要素の下位8ビットが１バイトのバイナリ値として出力されます。</p>



<p>countが*の場合、全ての要素が変換されます。リスト内の要素数が、countより大きい場合、余分な要素は無視されます。リスト内の要素数が、countより少ない場合、エラーになります。</p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary format c3cc* {3 -3 128 1} 260 {2 5}
=&gt; \x03\xfd\x80\x04\x02\x05 に相当するバイナリ値を返します。
</pre>



<p>以下はエラーになります。</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary format c {2 5}
=&gt; expected integer but got "2 5"

binary fomat c3 {2 5}
=&gt; number of elements in list does not match count
</pre>



<p>[参考]</p>



<pre class="nohighlight">　  3 : 0000 0011
   -3 : 1111 1101 参:<a href="https://blog.it-see.net/it-dokata/tcl-tk/bitwise-operator/#toc5" target="_blank">ビットごとのNOT(1の補数)</a>のメモを参照
　128 : 1000 0000 16進で80
　　1 : 0000 0001 countに3を指定しているので無視されます。
　260 : 0001 0000 0100 下位8ビットが変換対象の為、04を出力する。
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>s</strong></span><br>1つ以上の16ビット整数値をリトルエンディアン（little-endian）順に出力します。</p>



<p>16ビット(2バイト)の内、最下位バイトを先に出力します。それ以外は<strong>c</strong>と同じです。</p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary format s3 {3 -3 258 1}
=&gt; \x03\x00\xfd\xff\x02\x01 に相当するバイナリ値を返します。
</pre>



<p>[参考]</p>



<pre class="nohighlight">　258 : 0000 0001 0000 0010 16進で102
          0    1    0    2
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>S</strong></span><br>1つ以上の16ビット整数値をビッグエンディアン（big-endian）順に出力します。</p>



<p>16ビット(2バイト)の内、最上位バイトを先に出力します。それ以外は<strong>s</strong>と同じです。</p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary format S3 {3 -3 258 1}
=&gt; \x00\x03\xff\xfd\x01\x02 に相当するバイナリ値を返します。
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>t</strong></span><br>Tclスクリプトが実行されているマシンのネイティブのバイト順で16ビット整数を出力することを除いて、sおよびSと同じです。 </p>



<p>マシンのネイティブのバイト順が何であるかを判断するには、tcl_platform配列のbyteOrder要素を参照してください。</p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">puts $tcl_platform(byteOrder)
=&gt; littleEndian
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>i</strong></span><br>1つ以上の32ビット整数値をリトルエンディアン（little-endian）順に出力します。</p>



<p>32ビット(4バイト)の内、最下位バイトを先に出力します。それ以外は<strong>c</strong>と同じです。</p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary format i3 {3 -3 65536 1}
=&gt; \x03\x00\x00\x00\xfd\xff\xff\xff\x00\x00\x01\x00
   に相当するバイナリ値を返します。
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>I</strong></span><br>1つ以上の32ビット整数値をビッグエンディアン（big-endian）順に出力します。</p>



<p>32ビット(4バイト)の内、最上位バイトを先に出力します。それ以外は<strong>i</strong>と同じです。</p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary format I3 {3 -3 65536 1}
=&gt; \x00\x00\x00\x03\xff\xff\xff\xfd\x00\x01\x00\x00
　 に相当するバイナリ値を返します。
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>n</strong></span><br>Tclスクリプトが実行されているマシンのネイティブのバイト順で32ビット整数を出力することを除いて、<strong>i</strong>および<strong>I</strong>と同じです。</p>



<p>マシンのネイティブのバイト順が何であるかを判断するには、tcl_platform配列のbyteOrder要素を参照してください。</p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">puts $tcl_platform(byteOrder)
=&gt; littleEndian
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>w</strong></span><br>1つ以上の64ビット整数値をリトルエンディアン（little-endian）順に出力します。</p>



<p>64ビット(8バイト)の内、最下位バイトを先に出力します。それ以外は<strong>c</strong>と同じです。</p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary format w 7810179016327718216
=&gt; HelloTcl に相当するバイナリ値を返します。
</pre>



<p>[参考]<br>・16進数に変換すると</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">puts [format %x 7810179016327718216]
=&gt; 6c63546f6c6c6548 
</pre>



<pre class="nohighlight">16進 ：6c 63 54 6f 6c 6c 65 48 
ASCII： l  c  T  o  l  l  e  H　
=&gt; 最下位バイトから出力すると HelloTcl
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>W</strong></span><br>1つ以上の64ビット整数値をビッグエンディアン（big-endian）順に出力します。</p>



<p>64ビット(8バイト)の内、最上位バイトを先に出力します。それ以外は<strong>w</strong>と同じです。</p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary format Wc 4785469626960341345 110
=&gt; BigEndian に相当するバイナリ値を返します。
</pre>



<p>[参考]<br>・16進数に変換すると</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">puts [format "%x %x" 4785469626960341345 110]
=&gt; 426967456e646961 6e
</pre>



<pre class="nohighlight">16進 ：42 69 67 45 6e 64 69 61 6e
ASCII： B  i  g  E  n  d  i  a  n
=&gt; 最上位バイトから出力すると BigEndian
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>m</strong></span><br>Tclスクリプトが実行されているマシンのネイティブのバイト順で64ビット整数を出力することを除いて、<strong>w</strong>および<strong>W</strong>と同じです。</p>



<p>マシンのネイティブのバイト順が何であるかを判断するには、tcl_platform配列のbyteOrder要素を参照してください。</p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">puts $tcl_platform(byteOrder)
=&gt; littleEndian
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>f</strong></span><br>１つ以上の単精度浮動小数点数を、マシンのネイティブ表現で出力します。</p>



<p>この表現はアーキテクチャ間で移植性がないため、ネットワーク上で浮動小数点数を通信するために使用しないでください。</p>



<p>浮動小数点数のサイズはアーキテクチャによって異なりますので、生成されるバイト数は異なります。</p>



<p>値がマシンのネイティブ表現をオーバーフローすると、システムによって定義されたFLT_MAXの値が代わりに使用されます。 Tclは内部で倍精度浮動小数点数を使用しているため、単精度への変換では精度がいくらか低下する可能性があります。</p>



<p>たとえば、Intel(R) Core(TM) i7-4770 CPU上で実行されているWindowsシステムでは、</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary format f2 {1.6 3.4}
=&gt; \xcd\xcc\xcc\x3f\x9a\x99\x59\x40
   に相当するバイナリ値を返します。
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>r</strong></span><br>単精度浮動小数点数をリトルエンディアン順に格納することを除いて、<strong>f</strong>と同じです。</p>



<p>この変換は、IEEE浮動小数点表現を使用するマシンで使用された場合にのみ意味のある出力を生成します（非常に一般的ですが、ユニバーサルではありません）。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator"/>



<p><span class="fz-24px"><strong>R</strong></span><br>単精度浮動小数点数をビッグエンディアン順に格納すること以外は<strong>r</strong>と同じです。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>d</strong></span><br>１つ以上の倍精度浮動小数点数を、マシンのネイティブ表現で出力します。それ以外は、<strong>f</strong>と同じです。</p>



<p>たとえば、Intel Pentiumプロセッサ上で実行されているWindowsシステムでは、</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary format d1 {1.6}
=&gt; \x9a\x99\x99\x99\x99\x99\xf9\x3f
   に相当するバイナリ値を返します。
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>q</strong></span><br>倍精度浮動小数点数をリトルエンディアン順に格納することを除いて、<strong>d</strong>と同じです。</p>



<p>この変換は、IEEE浮動小数点表現を使用するマシンで使用された場合にのみ意味のある出力を生成します（非常に一般的ですが、ユニバーサルではありません）。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator"/>



<p><span class="fz-24px"><strong>Q</strong></span><br>倍精度浮動小数点数をビッグエンディアン順で格納することを除いて<strong>q</strong>と同じです。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>x</strong></span><br>count個のnullバイトを出力します。countが指定されていない場合は、1バイトのnullを出力します。countが*の場合、エラーが発生します。 </p>



<p>このタイプは引数を消費しません。 例えば、</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary format a3xa3x2a3 abc def ghi
=&gt; abc\000def\000\000ghi に相当するバイナリ値を返します。
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>X</strong></span><br>出力データのカーソル位置をcountバイト後ろに戻します。</p>



<p>countが*または現在のカーソル位置よりも大きい場合、カ－ソル位置は0に配置され、出力されている次のバイト値が最初のバイト値になります。countが省略された場合、カーソル位置は１バイト戻ります。</p>



<p>このタイプは引数を消費しません。例えば</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary format a3X*a3X2a3 abc def ghi
=&gt;  dghi に相当するバイナリ値を返します。
</pre>



<p>[参考]</p>



<pre class="nohighlight">a3 ---------&gt; abc_ カーソル位置3
a3X* -------&gt; abc  カーソル位置が0に戻る
a3X*a3 -----&gt; def_ カーソル位置3
a3X*a3X2 ---&gt; def  カーソル位置が1に戻る。２バイト(2文字分)戻る。
a3X*a3X2a3 -&gt; dghi を返す。
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator is-style-wide"/>



<p><span class="fz-24px"><strong>@</strong></span><br>countで指定された出力データの絶対位置にカーソルを移動します。 </p>



<p>位置0は、出力ストリングの最初のバイトを表します。countがこれまでに格納された最後のバイトを超えた位置を参照している場合は、nullバイトが初期化されていない位置に配置され、カーソルは指定された位置に配置されます。 </p>



<p>countが*の場合、カーソルは出力データの現在の末尾に移動します。 countを省略すると、エラーが発生します。 </p>



<p>このタイプは引数を消費しません。 例えば、</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary format a5@2a1@*a3@10a1 abcde f ghi j
=&gt; abfdeghi\000\000j に相当するバイナリ値を返します。
</pre>



<p>[参考]</p>



<pre class="nohighlight">a5 --------------&gt; abcde_            カーソル位置5
a5@2 ------------&gt; abcde             カーソル位置2
a5@2a1 ----------&gt; abfde             カーソル位置3
a5@2a1@* --------&gt; abfde_            カーソル位置5
a5@2a1@*a3 ------&gt; abfdeghi_         カーソル位置8
a5@2a1@*a3@10 ---&gt; abfdeghi\000\000_ カーソル位置10
a5@2a1@*a3@10a1 -&gt; abfdeghi\000\000j を返す。
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>次ページは、「binaryコマンドの日本語の扱いについて」</p>


]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Tcl &#8211; バイナリデータの操作(1)</title>
		<link>https://blog.it-see.net/it-dokata/tcl-tk/binary-operetion/</link>
		
		<dc:creator><![CDATA[いっしー]]></dc:creator>
		<pubDate>Tue, 29 Oct 2019 06:19:15 +0000</pubDate>
				<category><![CDATA[Tcl/Tk]]></category>
		<guid isPermaLink="false">https://blog.it-see.net/it-dokata/?p=1303</guid>

					<description><![CDATA[目次 バイナリデータを扱うバイナリデータのファイルを読み書きするバイナリデータのファイルを読み込む特定箇所のバイナリデータを読み込むバイナリデータの書き込み バイナリデータを扱う Tclは基本的に文字列データを操作するよ [&#8230;]]]></description>
										<content:encoded><![CDATA[

  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-14" checked><label class="toc-title" for="toc-checkbox-14">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">バイナリデータを扱う</a></li><li><a href="#toc2" tabindex="0">バイナリデータのファイルを読み書きする</a><ol><li><a href="#toc3" tabindex="0">バイナリデータのファイルを読み込む</a></li><li><a href="#toc4" tabindex="0">特定箇所のバイナリデータを読み込む</a></li><li><a href="#toc5" tabindex="0">バイナリデータの書き込み</a></li></ol></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">バイナリデータを扱う</span></h2>



<p>Tclは基本的に文字列データを操作するようになっています。Tcl8.0からバリナリデータを操作する為にbinaryコマンドが追加されました。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[書式]</p>



<pre class="nohighlight"><strong>binary format</strong> <em>formatString</em> ?<em>arg arg ...</em>?
<strong>binary scan</strong> <em>string formatString</em> ?<em>varName varName ...</em>?
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><strong>binary</strong>コマンドの第１引数に<strong>format</strong>を指定すると、文字列をバイナリに変換します。第１引数に<strong>scan</strong>を指定した場合はバイナリデータを文字列に変換します。</p>



<p><strong><span class="marker-under">binary</span></strong><span class="marker-under">コマンドを使うと文字列とバリナリデータを相互に変換することができます。</span></p>



<p><strong>binary</strong>コマンドのオプションは多数あります。最初にオプションを１つ１つ説明するよりも、まずは、バイナリデータの操作例を見て頂いてから、オプションの説明をした方が理解しやすいと思うので、バイナリデータの操作方法を紹介します。</p>



<p>バイナリデータの操作方法の説明でわからない部分は、オプションの説明を見た後に、再度バイナリデータの操作方法を見て頂くと、意味がわかるのではないかと思います。</p>



<p>※ファイルは前回使用のstr.txtを使います。</p>



<pre class="nohighlight">Hello! Hello!
Good morning!
Bye bye!
Have a nice day!
こんにちわ
おはようございます。
バイバイ
よい1日を！
</pre>



<p>[注意]<br>str.txtはUTF-8でエンコードされた文字列が書き込まれたファイルです。この記事の説明は、Tclの内部コードがUnicode(U+xxxx相当)で符号化方式をUTF-8で使用している環境で説明しています。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc2">バイナリデータのファイルを読み書きする</span></h2>



<p>バイナリデータを読み書きする方法を紹介します。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc3">バイナリデータのファイルを読み込む</span></h3>



<p>以下の例はバイナリデータのファイルを読み込んだ例です。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[使用例]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">$ tclsh

% set fid [open str.txt r]
file5
% fconfigure $fid -translation binary
% puts [read $fid]                  
Hello! Hello!
Good morning!
Bye bye!
Have a nice day!
ããã«ã¡ã
ãã¯ããããã
                 ã¾ãã
ã

</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>str.txtを文字データではなくバリナリデータとして読み込むには読み込むチャネルの設定を以下のように、binary に変更します。</p>



<pre class="tcl">fconfigure $fid -translation binary</pre>



<p style="text-align:center">または</p>



<pre class="tcl">chan configure $fid -translation binary</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><strong><span class="marker-under">-translation </span><em><span class="marker-under">binary</span></em></strong><span class="marker-under"> を指定すると、改行コードの変換や、ファイルの終端(null)、文字コードのエンコードが無効にされます。</span></p>



<p>よって、readコマンドやgetsコマンドで読み込んだデータはただのバイトデータとして扱われます。</p>



<p>バイトデータが英数字(asciiコード)の範囲内であれば、文字として画面へ出力されますが、範囲外のバイトデータはエンコードが無効の為、文字化けします。</p>



<p>以下は、str.txtをUNIXのhexdumpコマンドで出力したものです。</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">$ hexdump str.txt -C
00000000  48 65 6c 6c 6f 21 20 48  65 6c 6c 6f 21 0a 47 6f  |Hello! Hello!.Go|
00000010  6f 64 20 6d 6f 72 6e 69  6e 67 21 0a 42 79 65 20  |od morning!.Bye |
00000020  62 79 65 21 0a 48 61 76  65 20 61 20 6e 69 63 65  |bye!.Have a nice|
00000030  20 64 61 79 21 0a <u>e3 81  93 e3 82 93 e3 81 ab e3</u>  | day!...........|
00000040  <u>81 a1 e3 82 8f 0a</u> e3 81  8a e3 81 af e3 82 88 e3  |................|
00000050  81 86 e3 81 94 e3 81 96  e3 81 84 e3 81 be e3 81  |................|
00000060  99 e3 80 82 0a e3 83 90  e3 82 a4 e3 83 90 e3 82  |................|
00000070  a4 0a e3 82 88 e3 81 84  31 e6 97 a5 e3 82 92 ef  |........1.......|
00000080  bc 81 0a                                          |...|
00000083

0a:改行コード(\n)
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>str.txtの文字列「こんにちわ」は、10進で55バイト目(16進で36バイト目)の位置にあります。</p>



<p>UTF-8では１文字を、ASCIIコードの範囲内は1バイト、それ以外の文字は2～6バイドで符号化します。0a(改行)までが1行の文字列なので、「こんににわ」の5文字は、1文字3バイトで構成されており、合計15バイトあることがわかります。</p>



<pre class="nohighlight">e38193 e38293 e381ab e381a1 e3828f 0a
　こ　　 ん　　 に　　 ち　　 わ　 \n
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc4">特定箇所のバイナリデータを読み込む</span></h3>



<p><strong>binary scan</strong>を使ってバイナリデータを文字列に変換する。</p>



<p>以下の例は、str.txtの「こんにちわ」の部分をバイナリデータとして読み込んで、読み込んだバイナリデータを16進数の表記と文字に変換させています。</p>



<p>[使用例]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">$ tclsh

% set fid [open str.txt r]
file5
% fconfigure $fid -translation binary

% seek $fid 54 start              ----(1) 現在位置を移動
% set str [read $fid 16]          ----(2) 16バイド分を読み込み
ããã«ã¡ã

% binary scan $str H* tmp         ----(3.1) 16進数に変換
1
% puts $tmp                       ----(3.2) 16進数で表示
e38193e38293e381abe381a1e3828f0a

% puts [encoding convertfrom utf-8 $str] ----(4) 文字コードに変換
こんにちわ

% close $fid
% exit
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><strong>(1) 現在位置を移動</strong><br>hexdumpの出力結果から、「こんにちわ」は10進で55バイト目にあることがわかっています。よって、<span class="marker-under">直前の54バイト目まで現在位置をseekコマンドで移動させます。</span></p>



<p><strong>(2) 16バイド分を読み込み</strong><br>通常readコマンドの引数には文字数で指定します。binaryの指定によりエンコード・改行変換が無効になり、ただのバイトデータとして扱われるので、<span class="marker-under">１文字１バイト(1バイト文字)として指定する。</span>「こんにちわ」+ 改行(0a)の16バイト読み込む。読み込んだデータは文字の扱いではないので画面へ出力すると文字化けします。</p>



<p><strong>(3) 16進数に変換・表示</strong><br>読み込んだ<span class="marker-under">バイナリデータを</span><strong><span class="marker-under">binary scan</span></strong><span class="marker-under">コマンドを使って16進数表記に変えて出力しています。</span>引数Hは、バイナリデータを16進数表記の文字列に変換します。</p>



<p><strong>(4) utf-8 に変換</strong><br>変数strはバイナリデータなので、そのまま画面に出力すると文字化けします。</p>



<pre class="nohighlight"><strong>encoding convertfrom</strong> ?<em>encoding</em>? <em>data</em> 
</pre>



<p>このコマンドは、<em>data</em> を指定した <em>encoding</em> からUnicode(U+xxxx相当)に変換します。例の場合、変数strがUTF-8でエンコードされているとみなすので、結果的に文字として出力されます。</p>



<p>例えば、</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">encoding convertfrom utf-8 \xe3\x81\x93
encoding convertfrom shiftjis \x82\xb1
encoding convertfrom euc-jp \xa4\xb3
=&gt; こ
</pre>



<p>上の３つの引数detaの部分は、「こ」をそれぞれのエンコーディングで表した文字コードです。出力時は、システムの環境に合わせて出力されるのでUnix、Windows、Mac OS Xどの環境であっても、ひらがなの「こ」が表示されます。</p>



<p>Unicode(U+xxxx相当)のデータを、引数encodingで指定したエンコードのデータに変換するには、以下のようにします。</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">encoding convertto shiftjis \u3053
=&gt; 0x82b1 相当のバイナリデータ
</pre>



<p>ただし、変換された結果はTcl上では文字ではなくバイナリデータとしての扱いです。Unicodeの\u3053とSJISの0x82b1は平仮名の「こ」の文字コードになります。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">binary scan [encoding convertto shiftjis \u3053] H* str
=&gt; 1
puts $str
=&gt; 82b1
</pre>



<p>binary scanの引数formatStringに&#8221;H*&#8221;を指定すると、バイナリデータを16進コードの文字列に変換します。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc5">バイナリデータの書き込み</span></h3>



<p>binary formatを使って文字列をバイナリデータに変換する。</p>



<p>以下の例は、文字列と16進数の表記の文字列をバイナリデータに変換してファイルに書き込みしています。</p>



<p>[使用例]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">$ tclsh

% set str abcdefg           ----(1) 文字列
abcdefg
% set hex 00fffeaa55aa55ff  ----(2) 16進数
00fffeaa55aa55ff

% set fid [open hex.bin w]
file5
% fconfigure $fid -translation binary

% puts -nonewline $fid [binary format a* $str]  ----(3)
% puts -nonewline $fid [binary format H* $hex]  ----(4)

% close $fid
% exit

$ cat hex.bin          ----(5)
abcdefg���U�U�

$ hexdump hex.bin -C   ----(6)
00000000  61 62 63 64 65 66 67 00  ff fe aa 55 aa 55 ff     |abcdefg....U.U.|
0000000f
</pre>



<p><strong>(1)(2)</strong><br>文字列と16進数表記のデータを準備。</p>



<p><strong>(3)(4)</strong><br>引数aは、文字列データをバイナリデータに変換します。引数Hは、16進数表記の文字列をバイナリデータに変換します。</p>



<p><strong>(5)</strong><br>バイナリデータを書き込んだファイルなので、画面に出力すると文字化けします。</p>



<p><strong>(6)</strong><br>UNIXのhexdumpコマンドで確認すると、文字ではなくバイトデータとして書き込まれていることが確認できます。<br>*ASCIIコードの55は大文字の&#8221;U&#8221;です。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator"/>



<div class="blogcard-shortcode-wrap paragraph"> binary formatコマンドの使い方については以下の記事で紹介しています。<br><a href="https://blog.it-see.net/it-dokata/tcl-tk/binary-operetion2/" title="Tcl - バイナリデータの操作(2) -binary format-" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="160" height="107" src="https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/05/アイコン7-160x107.jpg" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/05/アイコン7-160x107.jpg 160w, https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/05/アイコン7-300x200.jpg 300w, https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/05/アイコン7-120x80.jpg 120w, https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/05/アイコン7-320x213.jpg 320w, https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/05/アイコン7.jpg 480w" sizes="(max-width: 160px) 100vw, 160px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">Tcl - バイナリデータの操作(2) -binary format-</div><div class="blogcard-snippet internal-blogcard-snippet">Tclでバイナリデータを取り扱うにはbinaryコマンドを使います。この記事ではbinary formatの引数 formatString に指定できる値と使い方について紹介します。</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://blog.it-see.net/it-dokata" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">blog.it-see.net</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2019.10.31</div></div></div></div></a> </div>



<div class="blogcard-shortcode-wrap paragraph">  binary scanコマンドの使い方については以下の記事で紹介しています。<br><a href="https://blog.it-see.net/it-dokata/tcl-tk/binary-operetion3/" title="Tcl - バイナリデータの操作(3) -binary scan-" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="160" height="107" src="https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/05/アイコン7-160x107.jpg" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/05/アイコン7-160x107.jpg 160w, https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/05/アイコン7-300x200.jpg 300w, https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/05/アイコン7-120x80.jpg 120w, https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/05/アイコン7-320x213.jpg 320w, https://blog.it-see.net/it-dokata/wp-docs/wp-content/uploads/2019/05/アイコン7.jpg 480w" sizes="(max-width: 160px) 100vw, 160px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">Tcl - バイナリデータの操作(3) -binary scan-</div><div class="blogcard-snippet internal-blogcard-snippet">Tclでバイナリデータを取り扱うにはbinaryコマンドを使います。この記事ではbinary scanの引数 formatString に指定できる値と使い方について紹介します。</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://blog.it-see.net/it-dokata" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">blog.it-see.net</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2019.11.07</div></div></div></div></a> </div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Tcl &#8211; ファイルの入出力(7) -seek,tell-</title>
		<link>https://blog.it-see.net/it-dokata/tcl-tk/file-io-operetion7/</link>
		
		<dc:creator><![CDATA[いっしー]]></dc:creator>
		<pubDate>Tue, 15 Oct 2019 07:44:42 +0000</pubDate>
				<category><![CDATA[Tcl/Tk]]></category>
		<guid isPermaLink="false">https://blog.it-see.net/it-dokata/?p=1296</guid>

					<description><![CDATA[この記事ではファイルのアクセス位置を変更するseekコマンドと現在のアクセス位置を取得するtellコマンドの使い方を紹介します。 seekコマンドとtellコマンド [書式] seek channelId offset  [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>この記事ではファイルのアクセス位置を変更するseekコマンドと現在のアクセス位置を取得するtellコマンドの使い方を紹介します。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">seekコマンドとtellコマンド</h2>



<p>[書式]</p>



<pre class="nohighlight"><strong>seek</strong> <em>channelId offset ?origin?</em></pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><strong>seek</strong>コマンドは<em>channelId</em>のアクセス位置を変更します。</p>



<p><em>offset</em>と<em>origin</em>は<em>channelId</em>の次の読み書きを行う位置を指定します。<em>offset</em>は整数でなければならず（負数でもよい）、<em>origin</em>は次のいずれかでなければならない。</p>



<p><strong>start</strong><br>新しいアクセス位置は、ファイルの先頭から<em>offset</em>で指定したバイト位置になります。</p>



<p><strong>current</strong><br>新しいアクセス位置は、現在のアクセス位置から<em>offset</em>で指定したバイト位置になります。<em>offset</em>に負数を指定すると、アクセス位置を後方に移動させます。</p>



<p><strong>end</strong><br>新しいアクセス位置は、ファイルの末尾から<em>offset</em>で指定したバイト位置になります。負数を指定すると、ファイルの終端の手前にアクセス位置を置き、正数を指定すると、ファイルの終端の後ろに置きます。</p>



<p><em>origin</em>のデフォルト値は<strong>start</strong>です。このコマンドは空文字列を返します。</p>



<div class="wp-block-cocoon-blocks-label-box-1 label-box lb-cyan block-box"><div class="label-box-label block-box-label fab-pencil"><span class="label-box-label-text block-box-label-text">メモ</span></div><div class="label-box-content">
<p><strong>注意</strong><br><em><span class="marker-under">offset</span></em><span class="marker-under">で指定する値は文字数ではなくバイト数です。</span><strong>read</strong>コマンドと違い文字ではなくバイトの観点で動作します。</p>
</div></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[書式]</p>



<pre class="nohighlight"><strong>tell</strong> <em>channelId</em></pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><strong>tell</strong>コマンドは、<em>channelId</em>の現在位置を返します。<strong>seek</strong>をサポートしないチャネルの場合、-1 を返します。このコマンドも、文字ではなくバイトの観点で動作します。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>※ファイルは前回の、str.txt を使用します。</p>



<pre class="nohighlight">
Hello! Hello!
Good morning!
Bye bye!
Have a nice day!
こんにちわ
おはようございます。
バイバイ
よい1日を！
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[使用例]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">
$ tclsh

# open時。
% set fid [open str.txt r]
file5
% tell $fid
0

# 3バイト進めて出力する。
% seek $fid 3
% puts [gets $fid]
lo! Hello!
% tell $fid
14

# 残りを出力する。
% puts [read -nonewline $fid]
Good morning!
Bye bye!
Have a nice day!
こんにちわ
おはようございます。
バイバイ
よい1日を！

% tell $fid
131
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>上の例は、3バイト進めた位置から１行分の出力を行い、残りをreadコマンドで出力しています。</p>



<p><a aria-label="ファイルの入出力(3) (新しいタブで開く)" href="https://blog.it-see.net/it-dokata/tcl-tk/file-io-operetion3/" target="_blank">ファイルの入出力(3)</a> のrw6a.tclで文字数の総数を数えるプログラムを紹介しましたが、最後のtellコマンドの結果は、文字数の総数より値が多く、文字ではなくバイトの観点で動作していることが分かります。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Tcl &#8211; ファイルの入出力(6) ファイル操作中のエラーを捕捉する</title>
		<link>https://blog.it-see.net/it-dokata/tcl-tk/file-io-operetion6/</link>
		
		<dc:creator><![CDATA[いっしー]]></dc:creator>
		<pubDate>Fri, 11 Oct 2019 07:55:13 +0000</pubDate>
				<category><![CDATA[Tcl/Tk]]></category>
		<guid isPermaLink="false">https://blog.it-see.net/it-dokata/?p=1291</guid>

					<description><![CDATA[目次 ファイルのエラー処理ファイルの存在を確認する &#8211; file existsエラーを捕捉する &#8211; catch ファイルのエラー処理 これまでファイルの入出力(x)で紹介したファイルを開く操作はフ [&#8230;]]]></description>
										<content:encoded><![CDATA[

  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-18" checked><label class="toc-title" for="toc-checkbox-18">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">ファイルのエラー処理</a></li><li><a href="#toc2" tabindex="0">ファイルの存在を確認する &#8211; file exists</a></li><li><a href="#toc3" tabindex="0">エラーを捕捉する &#8211; catch</a></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">ファイルのエラー処理</span></h2>



<p>これまでファイルの入出力(x)で紹介したファイルを開く操作はファイルオープンする際のエラーを考慮していませんでした。</p>



<p>ファイルを開く際に発生するエラー(ファイルの有無など)をcatchコマンドまたはfile existsコマンド使って捕捉し、エラー処理を行う方法を２つ紹介します。</p>



<p>※ファイルは前回の、str.txt を使用します。</p>



<p>[str.txt]</p>



<pre class="nohighlight">
Hello! Hello!
Good morning!
Bye bye!
Have a nice day!
こんにちわ
おはようございます。
バイバイ
よい1日を！
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc2">ファイルの存在を確認する &#8211; file exists</span></h2>



<p>ファイルを書き込みモードで開く方法として、これまで紹介したやり方は、openコマンドの引数に <strong>w</strong> または <strong>a</strong> を指定するものでした。</p>



<p>この指定方法では、存在しないファイルを指定すると新しいファイルを作成して処理を続行します。</p>



<p>ファイルが存在しない場合は処理を中止したり、存在しない為、新規で作成する旨の通知を行いたいこともあるかと思います。</p>



<p>また、ファイルを読み込む場合も、指定したファイルが存在しない場合には、メッセージを表示したいこともあると思います。</p>



<p>そういう時は、<strong>file</strong>コマンドの<strong>exists</strong>オプションでファイルの有無を確認できます。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[書式]</p>



<pre class="nohighlight"><strong>file exists</strong> <em>name</em></pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>ファイル名 <em>name</em> が存在し、現在のユーザーがそれに続くディレクトリに対する検索権限を持っている場合は1を返し、それ以外の場合は0を返します。</p>



<p>例えば、<a aria-label="ファイルの入出力(3) (新しいタブで開く)" href="https://blog.it-see.net/it-dokata/tcl-tk/file-io-operetion3/" target="_blank">ファイルの入出力(3)</a>で使用した、nl.tcl で、存在しないファイルを指定した場合、以下のエラーメッセージを画面に出力します。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">
$ ./nl.tcl aaa.txt
couldn't open "aaa.txt": no such file or directory
    while executing
"open $fname r"
    invoked from within
"set fid [open $fname r]"
    (file "./nl.tcl" line 10)
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>出力されたメッセージの内容を見るとエラーが発生したプログラムコードの箇所が表示されています。</p>



<p>Tclが出力するこのようなエラーメッセージを使用者には見せたくないという事もあると思います。</p>



<p>このエラーメッセージを画面に表示させなくするには次のサンプルのようにします。</p>



<p>以下のサンプルは file exists を使用して上記のエラーメッセージを表示させずに、「aaa.txt はありません」と表示するようにしています。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[サンプル] nl2.tcl </p>



<pre class="tcl">
#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "$@"

# 各行の先頭に行番号を付加して画面に出力する。

set fname [lindex $argv 0]    ;# ファイル名の取得

# ファイルの有無を確認後に読み込む。

if {[file exists $fname] == 1} {
    set fid [open $fname r]
    while {[gets $fid line] >= 0} {
        lappend strlst $line
    }
    close $fid

} else {
    puts "$fname はありません"
    exit  ;# プログラムの終了
}

# 各行の先頭に行番号を付ける。

set n 1    ;# 行番号
foreach tmp $strlst {
    puts [format "%03d : %s" $n $tmp]
    incr n
}
</pre>



<p>[実行例]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">
$ ./nl2.tcl aaa.txt
aaa.txt はありません

$ ./nl2.tcl str.txt
001 : Hello! Hello!
002 : Good morning!
003 : Bye bye!
004 : Have a nice day!
005 : こんにちわ
006 : おはようございます。
007 : バイバイ
008 : よい1日を！
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc3">エラーを捕捉する &#8211; catch</span></h2>



<p>catchコマンドは、引数の数が違っていたり、Tclコマンドやプロシージャを実行した際に発生するエラーを捕捉する為に使います。</p>



<p>エラーを捕捉する事で、プログラムの異常終了や中断するのを防ぎます。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[書式]</p>



<pre class="nohighlight">
<strong>catch</strong> <em>script</em> ?<em>resultVarName</em>? ?<em>optionsVarName</em>?
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>第１引数の<em>script</em>は、Tclコマンドやプロシージャを指定します。<br>第２引数の<em>resultVarName</em>は<em>script</em>の実行結果を保存する変数名を指定します。</p>



<p><em>script</em>でエラーが発生すると、<strong>catch</strong>コマンドは、例外的なリターンコードを示す0以外の整数値を返します。正常時は、0 (TCL_OK)を返します。</p>



<p>例外的なリターンコードとして以下が定義されています。</p>



<ol class="wp-block-list"><li>TCL_ERROR</li><li>TCL_RETURN</li><li>TCL_BREAK</li><li>TCL_CONTINUE</li></ol>



<p><em>resultVarName</em>が指定されている場合、scriptでエラーが発生すると、<em>resultVarName</em>には、エラーメッセージが格納されます。正常時は、<em>script</em>から返された値が格納されます。</p>



<p>※optionsVarNameの使い方については、catch, return のマニュアルを参照してください。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><strong>catch</strong>コマンドを使用してエラーを捕捉するには以下のようにします。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[サンプル]] nl3.tcl </p>



<pre class="tcl">
#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "$@"

# 各行の先頭に行番号を付加して画面に出力する。

set fname [lindex $argv 0]    ;# ファイル名の取得

# ファイルの読み込み。

if {[catch {open $fname r} fid]} {
    puts stderr "$fname がオープンできません"
    exit  ;# プログラムの終了
} else {
    while {[gets $fid line] >= 0} {
        lappend strlst $line
    }
    close $fid
}

# 各行の先頭に行番号を付ける。

set n 1    ;# 行番号
foreach tmp $strlst {
    puts [format "%03d : %s" $n $tmp]
    incr n
}
</pre>



<p>[実行例]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">
$ ./nl3.tcl aaa.txt
aaa.txt がオープンできません

$ ./nl3.tcl str.txt
001 : Hello! Hello!
002 : Good morning!
003 : Bye bye!
004 : Have a nice day!
005 : こんにちわ
006 : おはようございます。
007 : バイバイ
008 : よい1日を！
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>上のサンプルはTclのエラーを出力させずに「aaa.txt がオープンできません」と表示するようにしています。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="tcl">catch {open $fname r} fid</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>エラー発生時、第２引数の fid には、エラーメッセージが格納されますが、正常時は、ファイル識別子が格納されます。</p>



<p>上のサンプルでは、正常時のみ変数fidを使用しています。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="tcl">
puts stderr "$fname がオープンできません"
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>標準出力ではなく標準エラーに出力するようにしています。</p>



<p>これには理由がありまして、例えば、ファイルの内容や処理結果を標準出力へ出力するようなプログラムがあるとします。これをリダイレクションの機能を使って別のファイルへコピーしたとします。</p>



<p>例.</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">
$ ./xxxxx.tcl > tmp.txt
</pre>



<p>エラーメッセージを標準出力へ出力するようにしていると、コピー中にエラーが発生した場合、そのメッセージも一緒にコピーされてしまいます。</p>



<p>エラーメッセージを標準エラーに出力するようにしていると、エラーメッセージは画面に出力されるので、一緒にコピーされることを防ぐことができます。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading">catchコマンド及びTclで捕捉したエラーについて</h4>



<p>catchコマンドで捕捉したエラーは第２引数に格納されます。Tclで捕捉したエラーはTclのグロ－バル変数の<strong>errorInfo</strong>と<strong>errorCode</strong>に格納されています。</p>



<p>メッセージの違いを確認する為に、nl3.tcl のメッセージを出力する部分を以下のように書き換えて実行してみます。</p>



<pre class="tcl">
puts stderr "$fname がオープンできません"
puts stderr "fid  : $fid"
puts stderr "info : $errorInfo"
puts stderr "code : $errorCode"
</pre>



<p>[実行例]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">
$ ./nl3.tcl aaa.txt
aaa.txt がオープンできません
fid  : couldn't open "aaa.txt": no such file or directory
info : couldn't open "aaa.txt": no such file or directory
    while executing
"open $fname r"
code : POSIX ENOENT {no such file or directory}
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>「aaa.txt がオープンできません」だけでは分からないので以下のように出力するようにしてもいいかも知れません。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="tcl">
puts stderr "$fname がオープンできません\n$fid"
</pre>



<p>[実行例]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">
$ ./nl3.tcl aaa.txt
aaa.txt がオープンできません
couldn't open "aaa.txt": no such file or directory
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Tcl &#8211; ファイルの入出力(5) ファイルの文字コードと改行コードについて</title>
		<link>https://blog.it-see.net/it-dokata/tcl-tk/file-io-operetion5/</link>
		
		<dc:creator><![CDATA[いっしー]]></dc:creator>
		<pubDate>Thu, 03 Oct 2019 08:26:34 +0000</pubDate>
				<category><![CDATA[Tcl/Tk]]></category>
		<guid isPermaLink="false">https://blog.it-see.net/it-dokata/?p=1269</guid>

					<description><![CDATA[目次 chanコマンドについてファイルのコピーreadコマンドを使う方法fcopy(chan copy)コマンドを使う方法文字コードと改行コード chanコマンドについて Tcl8.5で入出力関係のコマンドが、chanコ [&#8230;]]]></description>
										<content:encoded><![CDATA[

  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-20" checked><label class="toc-title" for="toc-checkbox-20">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">chanコマンドについて</a></li><li><a href="#toc2" tabindex="0">ファイルのコピー</a><ol><li><a href="#toc3" tabindex="0">readコマンドを使う方法</a></li><li><a href="#toc4" tabindex="0">fcopy(chan copy)コマンドを使う方法</a></li></ol></li><li><a href="#toc5" tabindex="0">文字コードと改行コード</a></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">chanコマンドについて</span></h2>



<p>Tcl8.5で入出力関係のコマンドが、chanコマンドに集約されました。</p>



<p>以下の表の# xxxxx のコマンドが左側のchanコマンドに追加されています。</p>



<pre class="nohighlight">
      chan blocked    ; # fblocked
      chan close      ; # close
      chan configure  ; # fconfigure
      chan copy       ; # fcopy
      chan eof        ; # eof
      chan event      ; # fileevent
      chan flush      ; # flush
      chan gets       ; # gets
      chan names      ; # file channels
      chan puts       ; # puts
      chan read       ; # read
      chan seek       ; # seek
      chan tell       ; # tell
      chan truncate   ; # ftruncate

[非推奨]
      fblocked
      fconfigure
      fcopy
      fileevent
      file channels
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>非推奨になっているコマンドは今後、廃止になる可能性がある為、chanコマンドで書き換えができるよう選り分けることが勧められています。</p>



<div class="blogcard-shortcode-wrap paragraph">[参考]<br>
<a rel="noopener" href="https://core.tcl.tk/tips/doc/trunk/tip/208.md" title="Tcl Improvement Proposals: TIP 208: Add a &#8217;chan&#8217; Command" class="blogcard-wrap external-blogcard-wrap a-wrap cf" target="_blank"><div class="blogcard external-blogcard eb-left cf"><div class="blogcard-label external-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail external-blogcard-thumbnail"><img loading="lazy" decoding="async" src="https://s.wordpress.com/mshots/v1/https%3A%2F%2Fcore.tcl.tk%2Ftips%2Fdoc%2Ftrunk%2Ftip%2F208.md?w=160&#038;h=107" alt="" class="blogcard-thumb-image external-blogcard-thumb-image" width="160" height="107" /></figure><div class="blogcard-content external-blogcard-content"><div class="blogcard-title external-blogcard-title">Tcl Improvement Proposals: TIP 208: Add a &#8217;chan&#8217; Command</div><div class="blogcard-snippet external-blogcard-snippet"></div></div><div class="blogcard-footer external-blogcard-footer cf"><div class="blogcard-site external-blogcard-site"><div class="blogcard-favicon external-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://core.tcl.tk/tips/doc/trunk/tip/208.md" alt="" class="blogcard-favicon-image external-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain external-blogcard-domain">core.tcl.tk</div></div></div></div></a></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc2">ファイルのコピー</span></h2>



<p>ファイルをコピーするプログラムを２つ紹介します。</p>



<p>※ファイルは前回の、str.txt を使用します。</p>



<p>[str.txt]</p>



<pre class="nohighlight">
Hello! Hello!
Good morning!
Bye bye!
Have a nice day!
こんにちわ
おはようございます。
バイバイ
よい1日を！
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc3">readコマンドを使う方法</span></h3>



<p>[サンプル] copy1.tcl </p>



<pre class="tcl">
#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "$@"

# ファイルをコピーする

set fid1 [open str.txt r]
set fid2 [open str.cp1.txt w]

puts $fid2 [read -nonewline $fid1]

close $fid1
close $fid2
</pre>



<p>[実行例]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">
$ ls str*
str.txt

$ ./copy1.tcl
$ ls str*
str.cp1.txt  str.txt

$ cat str.cp1.txt
Hello! Hello!
Good morning!
Bye bye!
Have a nice day!
こんにちわ
おはようございます。
バイバイ
よい1日を！
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc4">fcopy(chan copy)コマンドを使う方法</span></h3>



<p>[書式]</p>



<pre class="nohighlight">
<strong>fcopy</strong> <em>inChan</em> <em>outCchan</em> ?<em>-size</em> size? ?<em>-command</em> callback?
<strong>chan copy</strong> <em>inChan</em> <em>outChan</em> ?<em>-size</em> size? ?<em>-command</em> callback?
</pre>



<p><strong>fcopy</strong>コマンドは、<em>inChan</em>から別の<em>outChan</em>にデータをコピーします。</p>



<p><em>-size</em>を指定しない場合、コピーはファイルの最後まで行われます。<em>-size</em>に指定するサイズは、2つのチャンネルが同じエンコーディングを使用している場合、サイズはバイトで、それ以外の場合は文字数です。</p>



<p><strong>-command</strong>を指定しない場合、<strong>fcopy</strong>はコピーが完了するまでブロックされ、<em>outChan</em>に書き込まれたバイト数または文字数を返します。</p>



<p><strong>-command</strong>を指定すると、<strong>fcopy</strong>はバックグラウンドで動作します。この場合、即座に戻り、callbackはコピーの完了後に呼び出されます。</p>



<p>callbackは、<em>outChan</em>に書き込まれたバイト数を示す1つまたは2つの追加の引数で呼び出されます。バックグラウンド・コピー中にエラーが発生した場合、2番目の引数はエラーに関連するエラー文字列です。</p>



<p>※ <strong>-size</strong>, <strong>-command</strong>を使用した例はここでは紹介しません。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[サンプル] copy2.tcl </p>



<pre class="tcl">
#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "$@"

# ファイルをコピーする その２

set fid1 [open str.txt r]
set fid2 [open str.cp2.txt w]

fcopy $fid1 $fid2

close $fid1
close $fid2

</pre>



<p>[実行例]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">
$ ./copy2.tcl
$ ls str*
str.cp1.txt  str.cp2.txt  str.txt

$ cat str.cp2.txt
Hello! Hello!
Good morning!
Bye bye!
Have a nice day!
こんにちわ
おはようございます。
バイバイ
よい1日を！
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>fcopyコマンドの代わりにchanコマンドを使う場合は以下のようにします。</p>



<pre class="tcl">chan copy $fid1 $fid2</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc5">文字コードと改行コード</span></h2>



<p>tclの内部では文字コードにUTF-8、改行コードはLFを採用していますが、入出力処理においての文字コードと改行コードは使用環境に自動的に合わせてくれます。</p>



<p>※ファイルの文字コードを自動的に変換してくれるという意味ではないです。</p>



<p>以下は主な環境で使われているパターンです。</p>



<p><strong>Windows</strong><br>文字コード：シフトJIS、改行コード：CR+LF(\r\n)<br>※正確には文字コード：CP932</p>



<p><strong>UNIXライクなOS</strong><br>文字コード：UTF-8、改行コード：LF(\n)<br>※古い環境では文字コード：EUCが使われている場合もあります。</p>



<p><strong>Mac OS X</strong><br>文字コード：UTF-8、改行コード：LF(\n)</p>



<p><strong>旧Mac(OS 9 以前)</strong><br>文字コード：シフトJIS、改行コード：CR(\r)<br>※正確には文字コード：MacJapanese</p>



<p>[補足]</p>



<p><strong>CP932</strong><br>マイクロソフトがShift_JISを独自に拡張した文字コード。よってCP932の文字コードで作成されたファイルの入出力にShift_JISを指定するとローマ数字など一部の文字で文字化けが発生します。</p>



<p><strong>MacJapanese</strong><br>アップルがShift_JISを独自に拡張した文字コード。よってCP932の文字コードで作成されたファイルの入出力にShift_JISを指定するとローマ数字など一部の文字で文字化けが発生します。</p>



<p><strong>LF</strong> : Line Feed(改行:0x0a)<br><strong>CR</strong> : Carriage Return(復帰:0x0d)</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><strong><span class="marker-red">Tclで使用できる主なエンコードの名前</span></strong></p>



<pre class="nohighlight">
　　iso2022-jp: JIS
　　shiftjis  : SJIS
　　euc-jp    : EUC
　　utf-8     : Unicode(UTF-8)
　　cp932     : MS-SJIS
　　macJapan  : 旧MACのSJIS
</pre>



<p>Tclで使用できるエンコードの名前は以下のコマンドで確認できます。</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">
$ tclsh
% encoding names
cp860 cp861 cp862 cp863 tis-620 cp864 cp865 cp866 gb12345 gb2312-raw cp949 cp950
cp869 dingbats ksc5601 macCentEuro cp874 macUkraine jis0201 gb2312 euc-cn 
euc-jp macThai iso8859-10 jis0208 iso2022-jp macIceland iso2022 iso8859-13
iso8859-14 jis0212 iso8859-15 cp737 iso8859-16 big5 euc-kr macRomania macTurkish
iso2022-kr gb1988 macGreek ascii cp437 macRoman iso8859-1 iso8859-2 iso8859-3 
macCroatian iso8859-4 koi8-r ebcdic iso8859-5 cp1250 macCyrillic iso8859-6 cp1251
macDingbats iso8859-7 koi8-u cp1252 iso8859-8 cp1253 iso8859-9 cp1254 cp1255 
cp850 cp1256 cp932 identity cp1257 cp852 macJapan cp1258 shiftjis utf-8 cp855 
cp936 symbol cp775 unicode cp857

</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>Tclでは、文字コードと改行コードを使用環境に合わせてくれるので同じ環境で使用する限りは気にする必要はありませんが、他の環境へファイルを持っていったり、他の環境で使われていたファイルを読み込む場合は、文字コードを変換する必要が生じる事があります。</p>



<p>以下のサンプルは文字コードをUTF8→CP932に変更した新しいファイルを作るプログラムです。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>[サンプル] enc.tcl</p>



<pre class="tcl">
#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "$@"

# utf-8 -> shiftjis(cp932) へ変更してコピーする

set fid1 [open str.txt r]
set fid2 [open str.sjis.txt w]

fconfigure $fid2 -translation crlf -encoding cp932

puts $fid2 [read -nonewline $fid1]

close $fid1
close $fid2
</pre>



<p>[実行例]</p>



<pre class="nohighlight" style="color: #ffffff; background-color: #000000;">
$ ./enc.tcl
$ ls str*
str.cp1.txt  str.cp2.txt  str.sjis.txt  str.txt

# そのまま表示させると文字化けする。
$ cat str.sjis.txt
Hello! Hello!
Good morning!
Bye bye!
Have a nice day!
�����ɂ���
���͂悤�������܂��B
�o�C�o�C
�悢1�����I


# 改行コードがCRLFで保存されていることを確認。
$ file str.sjis.txt
str.sjis.txt: Non-ISO extended-ASCII text, with CRLF line terminators

# iconvで文字コードを変換して表示させる。
$ iconv -f CP932 -t UTF-8 str.sjis.txt
Hello! Hello!
Good morning!
Bye bye!
Have a nice day!
こんにちわ
おはようございます。
バイバイ
よい1日を！
</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>上のサンプルでは、str.sjis.txtへ出力する際に使用する文字コードと改行コードをfconfigureコマンドで変更しています。</p>



<p>これも、fconfigureコマンドの代わりにchanコマンドを使う場合は以下のようにします。</p>



<pre class="tcl">chan configure $fid2 -translation crlf -encoding cp932</pre>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>iconvは比較的に新しいUNIXライクなOSであれば標準でインストールされていると思います。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>次回は、ファイルを開く時のエラー処理について紹介します。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p></p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
