シェルプログラミング入門 3

# はじめに

この記事は
[シェルプログラミング入門 1](https://qiita.com/twrcd1227/items/b7d6e16aa4e9f895a831)
[シェルプログラミング入門 2](https://qiita.com/twrcd1227/items/03310278eea64319b0e4)
の続編である。

# シェル関数

シェル関数は下のような形式である。

```sh
name()
{
    command
     ・・・・・
}
```

`ls -l`と同じ動作をする`lsl`という関数を作ってみる。

```sh
% lsl() {
> ls -l
> }
% lsl
total 48
-rw-r--r--  1 Tomoki  staff    7  4 16 09:23 abc
-rwxr-xr-x  1 Tomoki  staff  127  4 16 09:17 append*
-rwxr-xr-x  1 Tomoki  staff   25  5  2 12:14 kkk*
-rwxr-xr-x  1 Tomoki  staff   18  5  2 12:07 mmm*
-rwxr-xr-x  1 Tomoki  staff   45  5  2 11:51 nnn*
-rw-r--r--  1 Tomoki  staff   13  4 16 09:30 xyz
```

`$*`で引数をとれるようにしてみる。

```sh
% lsl() {
function> ls -l $*
function> }
% lsl *c
-rw-r--r--  1 Tomoki  staff  7  4 16 09:23 abc
```

これから基本的に関数内の変数には`_`で始めるようにする。

ちなみに以下のようなシェルスクリプトを作ったとき、そのまま実行してもシェルスクリプト内で定義されたコマンド(以下の場合 pse)を使うことができない。
そういうときには`.`コマンドを使って、`. script_file`のようにする。

```sh:aaa
% chmod +x aaa
% ./aaa
% pse
zsh: command not found: pse
% . ./aaa
% pse
  PID TTY           TIME CMD
    1 ??        12:58.82 /sbin/launchd
  136 ??         1:14.00 /usr/sbin/syslogd
      ・・・・・・・・
```

`.`コマンドを使って実行するシェルスクリプトには拡張子`.sh`をつけることが多い。また、直接実行しないように、モードは読み書きだけを許可し、ディレクトリも普通のコマンドとは分けられる。

# 組み込みコマンド

## null コマンド`:`

何もしないがいつも 0(true)を返すコマンド。

また、null ファイルを作ったり、ファイルの中身を消去したりすることができる。`%: > file`は`cp /dev/null file`や`cat /dev/null > file`と同じである。

## ドットコマンド`.`

先ほどシェル関数のところで出てきた`. file`という形で使うもの。
普通のコマンドと違い、新しくプロセスを作らず現行のシェルのプロセスを使って指定されたファイルを読み込み実行するもの。

## break コマンド

for や while のループから抜け出すときに使用するコマンド。
デフォルトでは 1 つのループを抜ける。
`break number`のように何個のループを抜けるか引数として指定できる。

## continue コマンド

for や while のループで,処理を中断し、次の繰り返しに移行させるコマンド
デフォルトでは次の繰り返しのステップに移行する。
`break number`のように何番目の繰り返しのステップに移行するか引数として指定できる。

## echo コマンド

引数の部分を標準出力に出力する。
`echo parameter`のようにして使う。

使っている UNIX(system V 系列か BSD 系列)によって出力方法が異なる。

## eval コマンド

eval コマンドは複数の置換などを 1 行のコマンドで全部展開する。

```sh
% VAR1=value
% VAR2=VAR1
% echo $"$VAR2"
$VAR1            #代入されない
% echo $$VAR2
22202VAR2
% echo $'$VAR2'
$VAR2
% echo \$$VAR2
$VAR1

#evalを使えばVAR1にも代入される
% eval echo \$$VAR2
value
% eval echo $"$VAR2"
value
```

また eval コマンドにはコマンドの結果が「何かを実行させるコマンドの形式をとって」返されたとき、それをそのまま実行させるというような場合にも利用される。

## exec コマンド

`exec command`のような形で使う。
新しくプロセスを作らず現行のカレントシェルのプロセスと置き換えて、引数のコマンドを実行させる。

## exit コマンド

シェルを終了するときに使う。
`exit number`のように番号を引数にすることでシェルスクリプトの終了コードを指定できる。
また、終了コードは$?変数に渡される。

## export コマンド

`export name`というふうに name で指定した変数を他のコマンドやシェルからも利用できるようにする。

## pwd コマンド

カレントディレクトリの完全パスを表示する。

## read コマンド

標準入力を読み取り、変数に代入する。

```sh:aa
#!/bin/sh
echo -n "enter yes or no --> "
read ANSWER
echo $ANSWER
```

```sh
% ./aa
-n enter yes or no -->
yes #yesと入力する
yes
```

## readonly コマンド

指定された変数を書き換え不可にする。変数に代入したり、unset したりできなくなる。
`readonly name...`のように使う。

## return コマンド

シェルの関数から抜けるコマンド。
引数が関数の返り値になる。

## set コマンド

シェルのオプションを ON にしたり OFF にしたりする。

```sh
% sh       #シェルの起動
$ echo abc
abc        #普通は結果のみ
$ set -v   #-vオプション(冗長モード)をつける
$ echo abc
echo abc   #結果の前に入力コマンドが表示される
abc
$ set +v   #-vオプションを元に戻す
set +v
$ echo abc
abc        #結果のみ
```

そのほかにもいろいろなオプションがある。 -をつけるとオプションが ON になり、+をつけると OFF になる。

`set parameter`のようにすると、位置パラメタに値をセットすることができる。

```sh:vvv
#!/bin/sh
echo $0 $1 $2 $3 $4
set aa bb cc
echo $0 $1 $2 $3 $4
```

これを実行すると

```sh
 % chmod +x vvv
% ./vvv 1 2 3 4 5
./vvv 1 2 3 4
./vvv aa bb cc
```

set コマンドによってそれまでの位置パラメタの値が全部クリアされる。

引数なしに`set`とすると、現在セットされている変数の一覧とその値が表示される。

## shift コマンド

位置パラメタの値を左にずらす

```sh:ooo
#!/bin/sh
echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9
shift
echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9
shift 3
echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9
shift $#       #位置パラメタをクリアする
echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9
```

位置パラメタを全部クリアするには`shift $#`とする。

これに引数を与えて実行すると

```sh
% chmod +x ooo
% % ./ooo aa bb cc dd ee ff gg hh ii
./ooo aa bb cc dd ee ff gg hh ii
./ooo bb cc dd ee ff gg hh ii
./ooo ee ff gg hh ii
./ooo
```

## test コマンド

条件を判定し、正しいとき０(true)を返す。

`test expression`もしくは`[ expression]`のように書く。

## trap コマンド

```sh
trap action signal...
```

signal に指定したシグナルを受け取ったときにどういう処理をするかを action のところに指定する。action はコマンドを並べたもの。

## type コマンド

コマンドが組み込みコマンドかどうかやコマンド本体のある場所を調べる。

```sh
% type echo date
echo is a shell builtin
date is /bin/date
```

## umask コマンド

ファイルを生成するときにモードを決定する。
`-rwxr-xr-x`や`-rw-r--r--`などがモードである。モードは 8 進数で表現され、r が 4, w が 2, x が 1 と考える。
例えば、`-rw-r--r--`は 644 となる。

```sh
umask mask
```

としてからファイルを作る(touch コマンドなどで)と、作成したファイルのモードは`666(対象がディレクトリなら777) - mask`となる。

何もせずにファイルを作ると umask の値は 022,つまり 644(読み書き移動可)となる。

## unset コマンド

指定した変数や関数を消去する。

```sh
unset name
```

## wait コマンド

引数に動作しているプロセス ID を指定し、
そのプログラムが終了するまで待つ。

```sh
command &
 ・・・・
wit $1
```

引数を指定しないとき、そのシェルから派生しているプロセスが全て終了するまで待ち状態となる。返り値は 0 となる。

# 参考

[シェルプログラミング入門 1](https://qiita.com/twrcd1227/items/b7d6e16aa4e9f895a831)
[シェルプログラミング入門 2](https://qiita.com/twrcd1227/items/03310278eea64319b0e4)