俺、昔cshで頑張ったよ

やっぱりポンコツで使えないな。昔はよく使ったけどbashで十分過ぎるし。
とりあえずcsh/tcshの特徴だけ挙げておこう。

## スペースを入れることができる
bourne shell や bash って変数に代入するときキモいよね。

```sh
$ 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だと普通にかけるのだが、、、

```sh
#!/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が使える

これだけはガチに便利。

```terminal
$ repeat 3 echo "ok"
ok
ok
ok
```


## alloc というbuiltinコマンド

tcshにて使用しているメモリの情報を表示してくれる。おおーと思ったけど、よくよく考えれば、こんなコマンド使う機会ないわ。

```sh
$ 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
```