シェルスクリプトの書き方を俺はもう忘れない、忘れてはいけないんだっっ！！

# なんだこれは
シェルスクリプト便利ですよね。
でも、**いっつも書き方忘れます**
もういい加減Google先生にコマンド単位で聞くの怠いので、書き方をまとめておく。

シェル芸ってレベルの記事じゃないですが、まあ、小さなスクリプト書く程度なら有益な記事です。たぶん。

オフビートで雑なエントリだけど気にしないでください。

# 基礎編
こっからシェルスクリプトの基本的な構文について書いていきます。マジで基本的な構文。

## 実行権限
意外と忘れがちだが、まず最初に権限を与えとこう。じゃなきゃ実行できねえ。

```shell
(*'~') $ touch sample.sh
(*'~') $ chmod +x ./sample.sh
```

## 宣言
*これはシェルスクリプトだ* って宣言を1行目に書くのを忘れるな。
shかbashの違いはそんなないのでbashでいいと思われる。

`#!/bin/bash`

## コメントアウト
コメントアウトは知っておきたいですよね。まあ、先頭に`#`つけるだけです。

```shell
(*'~') $ cat sample.sh  
#!/bin/bash

# echo "not display"
echo "display"
(*'~') $ ./sample.sh     
display
```

## 引数
引数や変数の書き方についてまとめるよ

### 引数の取り方
実際に書いて覚えるのが早い。引数の取り方は下記のスクリプトのように取れる。`$`で変数だよって意味。

```shell
(*'~') $ cat sample.sh 
#!/bin/bash

echo $#
echo $@
echo "$@"
echo $*
echo "$*"
echo $0
echo $1
echo $2
echo $9
```

試しに引数与えるとこんな感じになるよ。

```shell
(*'~') $ ./sample.sh hoge 1    
2
hoge 1
hoge 1
hoge 1
hoge 1
./sample.sh
hoge
1

(*'~') $ 
```

説明
- `$#` : スクリプトに渡された引数の数
- `$@` : スクリプトに渡された全ての引数。
- `$*` : スクリプトに渡された全ての引数。ダブルコーテーションで囲なければ`$@`と同じ。
- `$0` : 実行されてるスクリプト名。
- `$n` : スクリプトに渡されたn番目の引数。与えた引数の範囲を越えると空文字を出力。10番目以降の引数は`${n}`と記述しないと展開できないよ。

#### `$@` と `$*` の違い
ダブルコーテーションで囲なければ`$@`と同じであるが、囲むと以下のように、引数毎に出力するか、まとめて一つの引数で出力するかの違いがある。

```shell
(*'~') $ cat sample.sh 
#!/bin/bash
for arg in "$@"
    do
      echo $arg
	done

for arg in "$*"
    do
      echo $arg
    done
(*'~') $ ./sample.sh hoge foo 1
hoge
foo
1
hoge foo 1
```

## 変数
引数で既に書いてるけど、変数を参照するときは`$`がつく。定義するときはつけない。
あと、注意点が**変数を定義する時に`=`の左右に空白は入れない事**。繋げて書こう。

```shell
(*'~') $ cat ./sample.sh 
#!/bin/bash

hoge="This is Hoge"
echo $hoge
(*'~') $ ./sample.sh    
This is Hoge
```

### 変数展開
文字列の中で変数を展開する。ダブルコーテーションの中で変数書くだけ。

```shell
(*'~') $ cat ./sample.sh
#!/bin/bash

hoge="This is Hoge"
echo "What is this? $hoge"

(*'~') $ ./sample.sh   
What is this? This is Hoge
```

### コマンドの実行結果
コマンドの実行結果を変数に格納できる。`$()`の中で実行したいコマンドを記述。

```shell
(*'~') $ cat ./sample.sh
#!/bin/bash

hoge=$(echo "This is Hoge")
echo "What is this? $hoge"

(*'~') $ ./sample.sh   
What is this? This is Hoge
```

## 条件分岐
先ほどもちょっと書いたけど、if、for、case文の書き方について記述するよ。

### `if`文
必ず使いますね。ちょっと癖がある。
比較演算子で`-n`とか`-z`とかあるけど、結構混乱するんで普通に`"" = "$hoge"` みたいな比較の方が簡単だと思います。
因みに、**変数は必ずダブルコートで囲んで文字列として比較してください**

```shell
(*'~') $ cat sample.sh 
#!/bin/bash

if [ "" = "$1" ]; then
  echo "params not given"
fi

if [ "" != "$1" ]; then
  echo "params given $1"
fi
(*'~') $ ./sample.sh 
params not given
(*'~') $ ./sample.sh hoge
params given hoge
```

#### `if ~ else`
これまたよく使う構文。`elif`って毎回忘れる。

```shell
(*'~') $ cat sample.sh   
#!/bin/bash

if [ "hoge" = "$1" ]; then
  echo "params is hoge"
elif [ "foo" = "$1"  ]; then
  echo "params is foo"
else
  echo "params are not hoge or foo"
fi
(*'~') $ ./sample.sh hoge
params is hoge
(*'~') $ ./sample.sh foo 
params is foo
(*'~') $ ./sample.sh other
params are not hoge or foo
```


### `for`文
さっきちょっとやったね

```shell
(*'~') $ cat sample.sh 
#!/bin/bash

for arg in "$@"
    do
      echo $arg
    done
(*'~') $ ./sample.sh hoge foo 1
hoge
foo
1
```

### `case`文
地味に使うよね

```shell
(*'~') $ cat sample.sh    
#!/bin/bash

case "$1" in
      hoge)
        echo "params is hoge"
        ;;
      foo)
        echo "params is foo"
        ;;
      *)
        echo "params are not hoge or foo"
        ;;
    esac
(*'~') $ ./sample.sh hoge 
params is hoge
(*'~') $ ./sample.sh foo 
params is foo
(*'~') $ ./sample.sh other
params are not hoge or foo
```

## ヒアドキュメント
地味に便利なヒアドキュメント。シェルでももちろん使えます。
最初のEOS部分をシングルコーテーションで囲むと変数展開はされません。
因みに、EOSは最初と最後の文字を揃えればなんでもいいです。慣習として全て大文字であれば。

```shell
(*'~') $ cat sample.sh   
#!/bin/bash

cat << EOS
    you can discribe multiple lines.
    $1
EOS

cat << 'EOS'
    $1
EOS
(*'~') $ ./sample.sh hoge
    you can discribe multiple lines.
    hoge
    $1
```

## 終了処理
スクリプトを途中で終了するにはexitコマンドに数字を与えます。`0`が正常終了で、`1`が異常終了です。主に引数が不足してる時に処理を止める時とかに使います。

```shell
(*'~') $ cat sample.sh 
#!/bin/bash

case "$1" in
      0)
        echo "success"
		exit 0
        ;;
      *)
        echo "error"
		exit 1
        ;;
    esac

echo "can't reach"
(*'~') $ ./sample.sh 0
success
(*'~') $ ./sample.sh 1
error
```

# まとめ
こんなもんでどうだろう。

体系的に記述してるエントリーが意外となかった(たぶん探し方が悪い)ので、書いてみました。
やっぱり自分で書くとなんかわかった気になりますね。

後日に応用編を追加していきます。