LoginSignup
3

More than 5 years have passed since last update.

俺、昔cshで頑張ったよ

Posted at

やっぱりポンコツで使えないな。昔はよく使ったけど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

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
3