0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

tcl 引数処理

Last updated at Posted at 2019-11-11

まえがき

起動スクリプトから起動先の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追記

open
文字列操作

標準入力からの読み込み。パイプ経由からの場合とそれ以外の場合で書いてみた。
コマンドラインからの入力はコマンド置換結果をダブルクォートで囲んであげないと、意図した動きにならない。
もっといい書き方があれば知りたい。

$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}

パイプ経由引数
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?