まえがき
起動スクリプトから起動先のtclスクリプトに引数を渡す際のメモ。
スクリプト
パタン1
起動元スクリプトで引数のダブルクヲートつけてみる。
$cat caller.sh
# !/bin/bash
file="$1"
shift
args="$@"
exec tclsh "${file}" "$0" "${args}"
$cat callee.tcl
# !/usr/bin/tclsh
puts $argv0
puts $argc
puts $argv
実行結果
グルーピングされている。
$./caller.sh callee.tcl {a..d}
callee.tcl
2
./caller.sh {a b c d}
引数の順番を入れ替えてみる。
$cat caller.sh
# !/bin/bash
file="$1"
shift
args="$@"
exec tclsh "${file}" "${args}" "$0"
$cat callee.tcl
# !/usr/bin/tclsh
puts $argv0
puts $argc
puts $argv
実行結果
順序が入れ替わってグルーピングされている。
$./caller.sh callee.tcl {a..d}
callee.tcl
2
{a b c d} ./caller.sh
パタン2
起動元スクリプトで引数のダブルクヲート外してみる。
$cat caller.sh
# !/bin/bash
file="$1"
shift
args="$@"
exec tclsh "${file}" "$0" ${args}
$cat callee.tcl
# !/usr/bin/tclsh
puts $argv0
puts $argc
puts $argv
実行結果
グルーピングされていない。すべて単一要素にフラット化されている。
$./caller.sh callee.tcl {a..d}
callee.tcl
5
./caller.sh a b c d
引数の順番を入れ替えてみる。
$cat caller.sh
# !/bin/bash
file="$1"
shift
args="$@"
exec tclsh "${file}" ${args} "$0"
$./caller.sh callee.tcl {a..d}
callee.tcl
5
a b c d ./caller.sh
実行結果
順序が入れ替わってもグルーピングされていない。すべて単一要素にフラット化されている。
$./caller.sh callee.tcl {a..d}
callee.tcl
5
a b c d ./caller.sh
あとがき
挙動面白いなー。
以上、ありがとうございました。
20191112追記
標準入力からの読み込み。パイプ経由からの場合とそれ以外の場合で書いてみた。
コマンドラインからの入力はコマンド置換結果をダブルクォートで囲んであげないと、意図した動きにならない。
もっといい書き方があれば知りたい。
$cat 標準入力.tcl
# !/usr/bin/tclsh
proc usage {} {
puts "
Usage:
\$[info script] \"\$(echo {a..g} | xargs -n3)\"
{{a b c} {d e f} g}
コマンドライン経由引数
\$echo {a..g} | xargs -n3 | [info script]
{{a b c} {d e f} g}
パイプ経由引数
\$echo {1..100} | xargs -n15 | [info script]
{{1 2 3 4 5 6 7 8 9 10 11 12 13 14 15} {16 17 18 19 20 21 22 23 24 25 26 27 28 29 30} {31 32 33 34 35 36 37 38 39 40 41 42 43 44 45} {46 47 48 49 50 51 52 53 54 55 56 57 58 59 60} {61 62 63 64 65 66 67 68 69 70 71 72 73 74 75} {76 77 78 79 80 81 82 83 84 85 86 87 88 89 90} {91 92 93 94 95 96 97 98 99 100}}
パイプ経由引数
"
exit 1
}
proc main {argc argv} {
if {$argc!=0} {
set input $argv
if {[string length $input]==0} {
usage
}
set input_done "[split [lindex $input 0] "\n"] {}"
set input_done_done [lrange $input_done 0 end-1]
set init_args "\{$input_done_done\}"
puts $init_args
puts ""
puts "コマンドライン経由引数"
} else {
set stdin [open "| cat -"]
set input [read $stdin]
if {[string length $input]==1} {
usage
}
set input_done "[split $input "\n"]"
set input_done_done [lrange $input_done 0 end-1]
set init_args "\{$input_done_done\}"
puts $init_args
puts ""
puts "パイプ経由引数"
}
}
main $argc $argv
実行例
$echo {1..30} | xargs -n15 | ./標準入力.tcl
{{1 2 3 4 5 6 7 8 9 10 11 12 13 14 15} {16 17 18 19 20 21 22 23 24 25 26 27 28 29 30}}
パイプ経由引数
$echo {1..20} | xargs -n15 | ./標準入力.tcl
{{1 2 3 4 5 6 7 8 9 10 11 12 13 14 15} {16 17 18 19 20}}
パイプ経由引数
$./標準入力.tcl "$(echo {a..z})"
{{a b c d e f g h i j k l m n o p q r s t u v w x y z}}
コマンドライン経由引数
$./標準入力.tcl "$(echo {a..z}|xargs -n12)"
{{a b c d e f g h i j k l} {m n o p q r s t u v w x} {y z}}
コマンドライン経由引数
$echo {a..z} | xargs -n1 | ./標準入力.tcl
{a b c d e f g h i j k l m n o p q r s t u v w x y z}
パイプ経由引数
$echo {a..z} | xargs -n25 | ./標準入力.tcl
{{a b c d e f g h i j k l m n o p q r s t u v w x y} z}
パイプ経由引数
$echo {a..z} | xargs -n26 | ./標準入力.tcl
{{a b c d e f g h i j k l m n o p q r s t u v w x y z}}
パイプ経由引数
$echo {a..a} | xargs -n1 | ./標準入力.tcl
{a}
パイプ経由引数
コマンド作成した際、そのテストデータ作成時に便利かなって思っている。
ただ、単一と複数の住み分けがうまくいけてない。課題。
剰余グルーピングして単一要素の際はカーリブランケット**{}**は外されている。index参照はきちんと効く!。
$tclsh
% set a {{a b c} {d e f} {g h i} j}
{a b c} {d e f} {g h i} j
% puts $a
{a b c} {d e f} {g h i} j
% puts [lindex $a 0 1]
b
% puts [lindex $a 3]
j
% puts [lindex $a 3 0]
j
単一か複数の問題はコマンドライン経由の引数を文字列長さ判定値を1から0に変更した。
# 単一文字
$./標準入力.tcl "$(echo a)"
{a}
コマンドライン経由引数
# 単一文字範囲指定
$./標準入力.tcl "$(echo {a..a})"
{a}
コマンドライン経由引数
# 単一空文字
$./標準入力.tcl ""
{}
コマンドライン経由引数
# 複数空文字
$./標準入力.tcl "" ""
{}
コマンドライン経由引数
# 未指定(キー入力待ち。Ctrl+Cでquit)
$./標準入力.tcl
^C
# パイプ経由の単一改行
$echo | ./標準入力.tcl
Usage:
# パイプ経由の単一文字
$echo a | ./標準入力.tcl
{a}
パイプ経由引数
# パイプ経由の単一空文字
$echo "" | ./標準入力.tcl
Usage:
# パイプ経由の単一文字
$echo "a" | ./標準入力.tcl
{a}
パイプ経由引数