- 北の空からみなみへ -
exblog staff

<< 砂場遊び /ワンライナー番外地 砂場遊び /3(やっぱワンライ... >>
砂場遊び /3.4 (ちょこっと後片付)
2018年 03月 04日
実は先日投稿のソースにはバグがある。(翌日にちょこっと手直し済み)
ワンライナー側ではなく、それを呼び出して >$msgbox.vbs としているところが不具合だ。

秒数が1桁だとポップアップしないので、スクリーンショットを撮るときは 09 のような形式で無理やりに動作させていた。
これは、リダイレクト記号の直前に1桁の数字があると、それを入出力デバイス番号とみなすという仕様による。
コマンドやパラメータ間を空白で区切るのがDOS系OSの基本流儀。なのではあるがこのリダイレクト記号直前のデバイス番号については、挙動がおかしいことに気づいた後しばらくして理解した。(ちなみに リダイレクトインの直前デバイス番号は 0< に、リダイレクトアウトの標準出力は 1> 、標準エラー出力は 2> になる)

そしてもう一つ、こちらはごくちいさなパフォーマンス劣化に過ぎないので実害はごくわずか。
vbscript(ファイル=$msgbox.vbs)を実行させるために、cscript.exe から実行させていたが、これは wscript.exe から呼び出す方が、僅かに早いようだ。
(なんとなくCUI=文字操作側のcscriptの方がキビキビ動きそうなものだが、GUIを操作するwscriptオブジェクトだからそちらが本職なのだと憶えよう)

上半分はwscript(9秒のタイムアウトで9.75秒)、
下半分はcscript(9.80秒)。
c0062295_21055058.gif


一方で、手直し前のコードだとタイムアウト設定のつもりの 秒数=9(第4引数) が、(ありはしない)デバイス番号と解釈されているらしく消えている。
そのため秒数設定が空文字となって、ノータイムで戻っている = 戻り値(エラーレベル)が、0 となっていることでまともに動いていないことがわかる。
上半分はcscript(ノータイムの戻りで1.72秒)、
下半分はwscript(1.70秒)。まあほとんど誤差に近いが、上下逆にしても同じ速さ順だから、違いがあるのは間違いではないようだ。
c0062295_21092064.gif


ところで、このリダイレクト記号直前の数字だが、1> は標準出力先を、2> は標準エラー出力先を切り替えるときに使用すると説明される。
となると、0> ではどうなるか、3> や 4> ではどうなるかを確かめずにはいられないのが人情ではないだろうか?
(まあ、痴的好奇心と言われてしまえば、これはそうなのかも)


連続する変数を代入する場合に重宝するのが、for /L の文だが、この(変数代入をする)for や (条件分岐判断をする)if 文は、果たしてコマンドだと言えるのだろうか?
確かに、30年も前のMSDOSリファレンスガイドにもコマンド一覧に載ってはいた。けれども、次の二点で他の内部コマンドとは毛色が異なっている印象がある。
  • for/L とか if/I とかのように、直後に(空白を挟まずに)/スイッチのパラメータをつけるとエラーとなる。
    (set/a とか dir/s などではスイッチ直前が空白でなくとも動作する)
  • call if とか、call for のような、callで呼び出して実行することはできない。
    (call echo.〜〜 や、call set 〜=〜〜 のような実行方法が、ほとんどのコマンドで可能なのとは対照的)
そんなことを確認するのも含めて、遅延展開を有効にした cmd.exe 下で実験してみた。
(ほんのすこし前に気づいたのですが、cmd/v:on/k prompt ^^^> ^&title enabledelayedexpansion<リターン>とやると、遅延展開を有効=バッチ内で setlocal enabledelayedexpansion を宣言中と同じように !変数! の形式が使用できて、プロンプトとコマンド窓タイトルでどのような設定状況か混乱しない砂場遊びが可能なのですね)



最初は一時変数を生成する for文に入れてやってみたが、1文字変数を直接リダイレクト記号前に置いても想定した動きはしてくれなかった。
そこでsetコマンドでリダイレクト文字を含む変数に置き換えて、最終的には 1>&2 とやると標準出力を標準エラー出力に切り替えられることを参考にして、&2 を &0 〜 &4 まで代入替えで挙動を確認した。
c0062295_19411798.gif
デバイス番号0は、本来が 0< とやるリダイレクトイン(標準入力)ハンドルだから、>&0 は無理なのはわかる。けれど、3番って何だろう? と、またちょっと謎が残ったのでした。(4番以降は完全に無理=ないらしい)


こちらは do という名の変数に 1〜4 の数字を 標準出力からデバイス con に echo する意図で設定し、それを実行した結果。
set do=echo 0 1^>con
    ↑ この変数 do を展開して実行している

展開された変数を直接実行の場合は、リダイレクト記号はリテラルな文字として echo され、
call で呼び出す形で実行の場合には、リダイレクト記号が機能していた。
c0062295_19413174.gif
なかなかに面白い結果になった。


こちらはおまけ(例によって屋上屋を重ねてる)
c0062295_19412751.gif



そうそう、これも忘れそうだから書いておこう。

前回 more 欄で choice コマンドもどきな駄作を披露しているが、あのルーチン内での無駄行数は 選択肢文字列を 区切り文字で表示する形式に整形することに費やしていた。
次のようにすると、割とすっきり1行化できた。

set $key= &for /L %%i in (0,1,5) do for %%c in ("!key:~%%i,1!") do if not "%%~c" equ "" set $key=!$key: /=!/%%~c

そして、表示小文字を大文字に変換したりもう少し手直ししているがまだ最適化できていないので、最適化完了後に記録しておきたいと思う。
[PR]
by bucmacoto | 2018-03-04 04:03 | &Tips;&code; | Trackback | Comments(0)
トラックバックURL : https://bucmac.exblog.jp/tb/29348451
トラックバックする(会員専用) [ヘルプ]
名前
URL
画像認証
削除用パスワード
<< 砂場遊び /ワンライナー番外地 砂場遊び /3(やっぱワンライ... >>
<< 砂場遊び /ワンライナー番外地 砂場遊び /3(やっぱワンライ... >>