[自分用]シェルスクリプト勉強まとめ

# シェルスクリプト入門

## はじめに
これは自分用に書いたまとめです。
誰かの勉強する際の役に立ったり、間違いなどフィードバックいただければ嬉しいなと思い投稿しました。


## 初歩

シェバン or シバンっていうらしい

```shell

#! /bin/bash
```

ディレクトリがコマンドの実行パスに含まれていないためシェルスクリプトを実行するには以下のようにする

```shell

./hello
```


一行に複数の命令を描きたい場合はセミコロンで区切る

```shell

echo 'hoge'; echo 'fuga'
```

コメントアウトは#を使う

```shell

# hoge
```

## 変数
変数を宣言
=イコールの前後に空白がないようにする

```shell

name="hoge"
```

$変数名、${変数}とすることで変数を使える

```shell

echo 'hello  $name’
echo 'hello  ${name}’
```

内容を書き換えて欲しくない変数を作る場合はreadonlyというキーワードをつける

```shell

readonly name = ‘hoge’
```

‘ ’シングルクオーテーションを使うと変数の中身が展開されない

```shell

echo 'hello4 ${name}’
```

**特殊変数**
実行時に値を渡すことができ、渡された値には$1、$2のようにアクセスすることができる

```shell

echo "hello $1"
```

実行時
./hello hoge
値を渡す

\$0 スクリプトの名前
\$#  引数の数
\$@ or $* すべての引数

## 実行時にユーザーから入力を受け付ける

```shell

read name
```

入力前にテキストを表示したい場合は-p(プロンプトオプション)を使ってあげる

```shell

read -p “Name: “ name
```


複数の値を一気に複数の変数に割り当てる

```shell

read -p "Pick 3 colors: " c1 c2 c3
echo $c1
echo $c2
echo $c3
```

**四つ入れると余った分は最後に全部入れられるから最後に二つ入る**

配列

```shell
colors=(red blue pink)
echo ${colors[0]}
echo ${colors[1]}
echo ${colors[2]}
すべての要素を表示する
echo ${colors[@]}
要素の個数を表示する
echo ${#colors[@]}
```

値を変更する

```shell

colors[1]=silver
```

要素を追加する

```shell

colors+=(green orange)
```


##数値計算をする
数値の計算には``を使う

```shell

echo `expr 5 + 2`
```
↑の場合、一部の文字をエスケープしたりしないといけないらしい

↓のような書き方もできる

```shell

echo $((5 + 2))
```

(( ))の中で変数を使う場合は、$がいらない
n=10
echo $((n=n+5))

bashでは基本的に整数の演算子かできない

```shell

echo $((10 / 3))
```

if文を使った条件分岐

```shell

read -p "Name? " name
if test "name" = "taguchi"
then
  echo "welcome"
fi
```
testじゃなくて[ ]を使って書くこともできる

```shell

read -p "Name? " name
if  [ "$name" = "taguchi" ]
then
  echo "welcome"
fi
```
elifも使える

```shell

read -p "Name? " name
if  [ "$name" = "taguchi" ]
then
  echo "welcome"
elif [ "$name" = "tanaka" ]
then
  echo "welcom tanaka"
else
  echo "you are not taguchi"
fi
```
thenを一行に書くこともできる

```shell
read -p "Name? " name
if  [ "$name" = "taguchi" ]; then
  echo "welcome"
elif [ "$name" = "tanaka" ]; then
  echo "welcom tanaka"
else
  echo "you are not taguchi"
fi
```

**文字列や数値の比較には(())か[[]]を使う
この場合は、変数に""をつけなくていい**


-z 文字列の長さが0かどうか
=~ 正規表現

```shell

read -p "Name? " name
if [[ -z $name ]]; then
  echo 'empty'
fi

read -p "Name? " name
if [[ $name =~ ^t ]]; then
  echo 'starts with t'
fi
```


種類を問わず存在しているか　-e
ファイルが問わず存在しているか　-f
ディレクトリが存在しているか -d

```shell

if [[ -f $0 ]]; then
  echo 'file exits...'
fi

if [[ -d $0 ]]; then
  echo 'dir exits...'
fi

read -p "Number? " n
if (( $n > 10 )); then
  echo 'bigger than 10'
fi
```

## ループ処理

```shell

forでループ処理
for i in 1 2 3 4 5
do
  echo $i
done
```

 ブレース展開できる

```shell

for i in {1..5}; do
  echo $i
done
```

```shell

for ((i=1; i<=5; i++)); do
  echo $i
done
```

```shell

colors=(red blue pink)
for color in ${colors[@]}; do
  echo $color
done
```

dateコマンドを実行すると日付が返ってくる。
この実行結果を受け取ってシェルスクリプトを実行する。

```shell

for item in $(date); do
  echo $item
done
```


whileループについて

```shell

while ((i < 10)); do
  ((i++))
  echo $i
done
```

ルートをスキップするcontinue、抜けるためのbreak

```shell

while (( i < 10 )); do
  ((i++))
  if (( $i == 2 )); then
    continue
  fi
  if (( $i == 8 )); then
    break
  fi
  echo $i
done
```

## while :
nullコマンド、いつでも条件が成立する
while true　みたいなイメージ

```shell

while :
do
  read -p "Command? " cmd
  if [[ $cmd == 'quit' ]]; then
    break
  else
    echo "$cmd"
  fi
done
```

## ファイルの内容を処理する

```shell

i=1
while read line; do
  echo $i "$line"
  ((i++))
done
```

パイプを使ってファイルの内容を渡す方法もある

```shell

cat ファイル | スクリプトを実行
```

## case文

```shell

read -p "Signal color? " color
case "$color" in
  red)
    echo "stop"
    ;;
  blue|green)
    echo "go"
    ;;
  yellow)
    echo "caution"
    ;;
  *)
    echo "wrong signal"
esac
```

## ユーザーに値を選んでもらえる　select
selectの中はループ処理になるため、breakで抜ける必要がある

```shell

select color in red blue yellow green; do
  case "$color" in
    red)
      echo "stop"
      ;;
    blue|green)
      echo "go"
      ;;
    yellow)
      echo "caution"
      ;;
    *)
      echo "wrong signal"
      break
  esac
done
```

## 関数を使ってみる

```shell

function hello() {
  echo "hello..."
}
```

functionは省略できる

```shell

function hello() {
  echo "hello..."
}

# 関数名を書けば実行される
hello
hello
```

関数には引数を渡すことができる

```shell

# 引数から受け取った値を使うには$
function hello() {
  echo "hello... $1"
}

# 関数名を書けば実行される
hello tanaka
hello yamamoto
```

## returnを使って関数が正常終了したかどうかの終了ステータスを返すことができる
UNIXの世界では0だと正常終了、それ以外の場合は以上終了を意味する

```shell

hello(){
  if [[ $1 == 'tanaka' ]]; then
    return 1
  else
    return 0
  fi
}

# 直前の関数の少量ステータスは$?で調べることができる
hello tanaka; echo $?
hello hoge; echo $?
```

## 終わり
基礎的なことしかやってないから時間がある時にもっと色々してみようと思います。
自分はシェルスクリプト書いてこんなことしてますとかコメントで教えていただけると嬉しいです。