シェルスクリプトの基礎知識

#はじめに
Linuc試験に向けてシェルスクリプトを勉強しましたので、そのアウトプットになります。
試験勉強で得た知識のため、あくまでもシェルスクリプト入門用の基礎知識となります。

#インタプリタの指定
シェルスクリプトでは、はじめにスクリプトを解釈させるインタプリタを指定します。
指定出来るインタプリタは、Bourneシェルやbash、python等があります。
「bash」などは多くの現場で使用されているかと思われます。

インタプリタの指定には、以下の3つの方法があります。
①スクリプトファイルの先頭行で指定する
②インタプリタをコマンド実行する
③スクリプトを実行したシェル自身を指定する

##スクリプトの先頭行で指定
インタプリタはスクリプトファイルの先頭行で指定する場合、
「#!」の後にシェルスクリプトを解釈させるインタプリタのパスを指定します。

例）

```shell
#!/bin/bash
```

もちろん、bash以外のインタプリタを指定可能です。

|インタプリタ | 記述 |
|-------|-------|
|Bourneシェル|　#!bin/sh |
|bash|　#!bin/bash |
|perl|　#!/usr/bin/perl |
|python|　#!/usr/bin/python |

##インタプリタをコマンド実行
インタプリタをコマンドとして実行する場合、
スクリプトファイルを引数に指定して実行します。

例）

```shell
$ bash ./sample.sh
```

この場合、コマンド実行されたインタプリタがスクリプトを解釈します。
そのため、スクリプトファイルの先頭行に「#!bin/sh」等があってもコメントとして無視されます。

##スクリプトを実行したシェル自身を指定
上記2つの実行方法は、スクリプト実行時にインタプリタを別途起動して実行しますが、
「.」、またはsourceコマンドの引数にシェルスクリプトを指定することで、操作中のシェル自身で実行することも可能です。

例）

```shell
$ . ./sample.sh
```

#権限
##実行に必要な権限
コマンドなど、バイナリ形式のものは実行権限があれば実行できますが、
シェルスクリプトの場合、実行権限と読込権限を必要とします。
##例外
ただし、
インタプリタをコマンドとして実行した場合、引数でしたスクリプトファイルには読込権限のみで実行出来ます。

#変数
Linuxの世界ではシェル変数と環境変数の2種類があります。

##シェル変数
シェル変数は設定したシェルでのみ使用出来る変数です。
そのため、シェルから生成された子プロセスでは参照することは出来ません。

###定義方法
シェル変数は「シェル変数=値」で定義できます。

例）hoge変数を定義し、文字列「hogehoge」を代入する

```shell
hoge="hogehoge"
```

##環境変数
環境変数は設定したシェルと、そのシェルによって生成された子プロセスで参照出来る変数です。

例）hoge変数を定義し、文字列「hogehoge」を代入する

```shell
export hoge="hogehoge"
```

###定義方法
環境変数はシェル変数をエクスポート宣言することで定義できます。

##変数を参照する
変数名の先頭に$変数名、または${変数名}で変数を参照出来ます。

```shell
$hoge
${hoge}
```

##変数を削除する
unsetコマンドで削除出来ます。

```
unset hoge
```

##コマンドの実行結果を変数に格納する
###コマンドを$()で囲んで変数に格納する
コマンドを$()で囲むと、その結果を変数に格納出来ます。

```shell
hoge = $(コマンド)
```

###コマンドを`「バッククォート」で囲む
コマンドを`「バッククォート」で囲むと、その結果を変数に格納出来ます。

```shell
hoge = `コマンド`
```

##特殊なシェル変数
###シェル自身のプロセスID
シェル変数「$$」からは「シェル自身のプロセスID」を参照出来ます。

```shell
$$
```

###最後に実行したコマンドの終了値
シェル変数「$?」からは「最後に実行したコマンドの終了値」を参照出来ます。

```shell
$?
```

###引数の個数
シェル変数「$#」からは「引数の個数」を参照出来ます。

```shell
$#
```

###区切り文字で区切られた全ての引数
シェル変数「$*」からは「区切り文字で区切られた全ての引数」を参照出来ます。
※区切り文字のデフォルトは空白になります

```shell
$*
```

###実行ファイル名
シェル変数「$0」からは「実行ファイル名」を参照出来ます。

```shell
$0
```

###1番目の引数、2番目の引数
シェル変数を「\$1,\$2...」とするとスクリプト実行時の引数を1番目、2番目...と参照出来ます。

```shell
$1
$2
.
.
```

#文字列
シェルスクリプトで文字列を扱う場合、多言語と同様に"「ダブルクォート」等で囲むことで利用出来ます。
しかし、囲む記号によって挙動が異なります。

##括る記号の種類
###"「ダブルクォート」で括る
文字列内に変数が存在する場合、変数を展開して文字列とします。
文字列内にコマンドが存在しても評価されず、そのまま文字列として扱います。

```shell
$ echo "$LANG aaa"
ja_JP.UTF-8 aaa
```

```shell
$ echo "echo aaa" 
echo aaa
```

###'「シングルクォート」で括る
文字列内に変数が存在しても展開せず、そのまま文字列として扱います。
文字列内にコマンドが存在しても評価されず、そのまま文字列として扱われます。

```shell
$ echo '$LANG aaa'
$LANG aaa
```

```shell
$ echo 'echo aaa'
echo aaa
```

###`「バッククォート」で括る
文字列内に変数が存在する場合、展開した結果を文字列として扱います。
文字列内にコマンドが存在する場合、評価した結果を文字列として扱います。

```shell
$ echo `$LANG aaa`
-bash: ja_JP.UTF-8: コマンドが見つかりません
```

```shell
$ echo `echo aaa`
aaa
```

#変数、文字列の結合
##変数同士を結合する

```shell
hoge3 = $hoge1$hoge2
```

##変数と文字列を結合する

```shell
str = "${hoge1} 文字列"
```

#条件分岐
if文を使って分岐処理を書きます。
if文の条件式となるコマンドの終了値が0であれば、if文内のコマンドが実行されます。

構文）

```shell
if コマンド1(条件式); then
    コマンド2
elif コマンド3(条件式); then
    コマンド4
else
    : #何もしない場合、未記載は不可のため文法上影響のない「:」を記載します
fi
```
※「;」は省略可能ですが、その場合は条件式の後は改行してthenを書く必要があります。

条件式となるコマンドは[「]コマンド、またはtestコマンドを使用します。

```shell
# 「[」 コマンドを使用した場合
if [ "hoge" = "hoge" ]; then
  echo "hoge"
fi

#testコマンドを使用した場合
if test "hoge" = "hoge"; then
  echo "hoge"
fi
```

#条件式
if文などで条件判定を行う場合、以下の条件式を使用します。

|条件式 | 説明 |
|-------|-------|
|-d ファイル名| ファイルが存在し、ディレクトリファイルなら真 |　
|-e ファイル名| ファイルが存在すれば真 |
|-f ファイル名| ファイルが存在し、通常ファイルなら真| 
|-x ファイル名| ファイルが存在し、実行可能なら真 |
|-n 文字列| 文字列ぼ長さが0より大きければ真 |
|-z 文字列| 文字列ぼ長さが0であれば真|
|文字列1 = 文字列2| 文字列1と文字列2が等しければ真 |
|文字列1 != 文字列2| 文字列1と文字列2が等くなければ真 |
|整数1 -eq 整数2| 整数1と整数2が等しければ真 |
|整数1 -ge 整数2| 整数1が整数2より大きいか等しければ真 |
|整数1 -gt 整数2| 整数1が整数2より大きければ真 |
|整数1 -le 整数2| 整数1が整数2より小さいか等しければ真 |
|整数1 -lt 整数2| 整数1が整数2より小さければ真 |
|整数1 -ne 整数2| 整数1と整数2が等しくなければ真 |

#繰り返し
シェルスクリプトも他言語と同様に繰り返し処理を書くことが出来ます。
繰り返し処理にはfor文とwhile文を使用します。

##for文
構文）

```shell
for シェル変数 in リスト
do
    コマンド
done
```

inの前の変数にinの後に指定したリストの要素を格納し、繰り返します。
よって、リストの要素の数だけループします。

##while文
構文）

```shell
while コマンド1
do
    コマンド2
done
```

コマンド1の終了値が0の間、コマンド2を繰り返します。

#関数
シェルスクリプトも他言語と同様に関数を書くことが出来ます。

##function
子プロセスを生成せずに現在のシェルで処理する関数
構文：

```shell
function 関数名 () { 
  コマンド郡 
}
```

##組込み関数
シェルスクリプトには組込み関数という、デフォルトで利用出来る関数も存在します。

例）shift関数
シェル実行時に指定した引数を

2番目を1番目に、
3番目を2番目に。。。

と前詰めします。

#参考文献

https://www.amazon.co.jp/Linux%E6%95%99%E7%A7%91%E6%9B%B8-LPIC-%E3%83%AC%E3%83%99%E3%83%AB1-%E3%82%B9%E3%83%94%E3%83%BC%E3%83%89%E3%83%9E%E3%82%B9%E3%82%BF%E3%83%BC%E5%95%8F%E9%A1%8C%E9%9B%86-Version5-0%E5%AF%BE%E5%BF%9C-ebook/dp/B07TVTKW2C/ref=sr_1_4?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=3KRXN24H8MM9U&dchild=1&keywords=lpic+%E3%83%AC%E3%83%99%E3%83%AB1&qid=1629635905&sprefix=lpic%2Caps%2C306&sr=8-4

https://eng-entrance.com/linux-shellscript-if