やっぱりポンコツで使えないな。昔はよく使ったけどbashで十分過ぎるし。
とりあえずcsh/tcshの特徴だけ挙げておこう。
スペースを入れることができる
bourne shell や bash って変数に代入するときキモいよね。
$ a = 1
-bash: a: command not found
$ a=1; echo $a
1
でもcshではスペースを入れても入れなくてもよい。これはbashよりcshのほうがいいね。
$ echo $a
1
$ set a=2
$ echo $a
2
配列のインデックス番号が1から始まる
こういうの止めてほしい。fortranやluaも1オリジン(one-base)だけど、なんか嫌です。
$ csh
$ set arr = (a b c)
$ echo $arr[0]
$ echo $arr[1]
a
$ echo $arr[2]
b
$ echo $arr[3]
c
しかしスライスっぽい使い方ができる。これはtcsh限定の機能かしら。
$ echo $arr[-1]
a
$ echo $arr[-2]
a b
$ echo $arr[-3]
a b c
$ echo $arr[1-2]
a b
$ echo $arr[1-3]
a b c
$ echo $arr[2-3]
b c
関数がない
関数が使えないからgotoで頑張る。頑張らないとダメなのか。aliasで頑張るには限度あるぞ。
#!/bin/csh
switch($#argv)
case 1:
goto _ONE
breaksw
case 2:
goto _TWO
breaksw
default :
goto _EOF
endsw
_ONE:
echo "one"
goto _EOF
_TWO:
echo "two"
goto _EOF
_EOF:
exit(0)
マクロのような書き方ができる
マクロじゃないんだけどね。こういう書き方は許していいのかね。
$ cat kimoi.csh
#!/bin/csh
if ($1 == 1) then
foreach x (a a a)
else
foreach x (b b b)
endif
echo $x
end
$ csh kimoi.csh 1
a
a
a
$ csh kimoi.csh 2
b
b
b
微妙に遅い
計算が遅いのか、イテレータが遅いのか知らんけど、なんか遅い。
$ cat total.csh
#!/bin/tcsh
set total = 0
foreach x (`seq 100000`)
@ total = $total + $x
end
echo $total
$ time tcsh total.csh
5000050000
real 0m2.270s
user 0m1.545s
sys 0m0.721s
bashのほうがだいたい4倍ぐらい速い。
$ cat total.sh
#!/bin/bash
set total = 0
for x in `seq 100000`
do
total=$((total+$x))
done
echo $total
$ time bash total.sh
5000050000
real 0m0.627s
user 0m0.590s
sys 0m0.036s
変数パラメータ展開が微妙に使える
少し使える。bashよりわかりやすい。
$ cat para.csh
#!/bin/csh
set a = "/path/to/cmd"
echo \$a is $a
echo \$a:h is $a:h
echo \$a:t is $a:t
$ csh para.csh
$a is /path/to/cmd
$a:h is /path/to
$a:t is cmd
シグナルトラップが微妙
一応ある。INTとTERMはトラップできるみたい。シグナルハンドラはgotoですか。
$ cat sigtrap.csh
#!/bin/csh
onintr MYTRAP
while(1)
sleep 1
echo -n "."
end
MYTRAP:
echo "trap!"
$ csh sigtrap.csh
...^C
trap!
シェルスクリプト内のawkが書きにくい
bashだと普通にかけるのだが、、、
#!/bin/bash
ls -l |\
awk '{
if ($0 ~/sh$/)
print $NF
}'
cshの場合はawkの構文箇所であっても改行入れる場合はエスケープをしないといけない。なんなの?
#!/bin/csh
ls -l |\
awk '{ \
if ($0 ~/sh$/) \
print hoge, $NF \
}'
謎の変数があったりする
バッククォートでのコマンド実行やパイプ処理でよくわからんステータス判定をする。
コマンド失敗しているけど、builtinの set
までは成功しているから、正常と判断するのね。
$ tcsh
$ unset anyerror
$ set a = `sl`
sl: Command not found.
$ echo $?
0
# 変数aは未定義じゃないから成功扱い?かな。
$ echo $?a
1
anyerror
を設定していると、コマンド失敗は失敗としてステータスを返してくれる。 CentOS7のtcshはanyerror
はデフォルト有効になっている。
$ set anyerror
$ set a = `sl`
sl: Command not found.
$ echo $?
1
repeatが使える
これだけはガチに便利。
$ repeat 3 echo "ok"
ok
ok
ok
alloc というbuiltinコマンド
tcshにて使用しているメモリの情報を表示してくれる。おおーと思ったけど、よくよく考えれば、こんなコマンド使う機会ないわ。
$ alloc
tcsh current memory allocation:
Total space allocated from system: 782336
Number of non-inuse chunks: 8
Number of mmapped regions: 0
Total space in mmapped regions: 0
Total allocated space: 670800
Total non-inuse space: 111536
Top-most, releasable space: 70464
# 適当に変数にでかい値を代入しておいて
$ set a = "`find /usr/bin`"
$ set b = "`find /usr/bin`"
$ set c = "`find /usr/bin`"
$ set d = "`find /usr/bin`"
$ set e = "`find /usr/bin`"
# メモリを再確認
$ alloc
tcsh current memory allocation:
Total space allocated from system: 1585152
Number of non-inuse chunks: 288
Number of mmapped regions: 0
Total space in mmapped regions: 0
Total allocated space: 1447760
Total non-inuse space: 137392
Top-most, releasable space: 81584