シェルとシェルスクリプト

# 環境変数とシェル変数

https://qiita.com/matuumo/items/737b55649ae5111f347e#%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0

### 変数の代入
コマンドの実行結果をシェル変数に代入することが出来る

+ コマンドを「**$()**」で囲んで、その結果をシェル変数に代入する
+ コマンドを「**`(バッククォート)**」で囲んで、その結果をシェル変数に代入する

### setコマンド
オプションを指定せずに実行すると、現在のシェルで定義されているシェル変数の一覧を表示する。

| オプション | 説明 |
|:-:|:-:|
| -o シェルオプション  | シェルオプションを有効にする  |
| +o シェルオプション  | シェルオプションを無効にする  |
| -o  | シェルオプションの設定状態の確認  |

| シェルオプション | 説明 |
|:-:|:-:|
| allexport  | 作成・変更した変数を自動的にエクスポートする  |
| emacs  | emacs風のキーバインドにする  |
| ignoreeof  | Ctrl＋Dによってログアウトしないようにする  |
| noclobber(-C)  | リダイレクションによる既存のファイルへの上書きを禁止する  |
| histexpand(-H)  | 「!番号」による履歴参照を行う（デフォルトで有効）  |
| noglob  | メタキャラクタを使ったファイル名展開を無効にする  |
| noexec  | シェルスクリプトを読み込むが、実行はせずに構文エラーのみ確認（検査）する  |


### envコマンド
**書式：env [オプション] [環境変数名＝値] [コマンド]**
環境変数を一時的に変更したり、削除したりしてコマンドを実行できる。指定した環境変数の値は、envコマンドで実行したコマンドにのみ反映される。
オプションに指定がない場合は、全ての環境変数を表示する

| オプション | 説明 |
|:-:|:-:|
| -i(--ignore-environment)  | 何も環境変数が設定されていない状態にする  |
| -u 環境変数名(--unset=変数名)  | 環境変数を一時的に削除  |
| 環境変数名=値  | 環境変数の値を一時的に指定された値に変更  |





### aliasコマンド
**書式:alias [エイリアス]='元のコマンド'**
コマンドに別名を付けたり、コマンドとオプションをひとまとめにして新しいコマンドのようにしたりすることができる。

### unaliasコマンド
エイリアスを解除するためのコマンド。[-a]オプションを付けることで全てのエイリアスを解除することが出来る。

::: note info
実行するコマンドの前に「\(バックスラッシュ)」を入れることで、一時的にエイリアスを使用しなくすることが出来る。
:::


# 関数の定義

### functionコマンド
~~~md
#書式
[function]関数名(){ 実行するコマンドのリスト；}

#書式
[function]
関数名()
{
    コマンド
}
~~~
bashシェル上で利用できる独自の関数を定義することが出来る。シェル内部で実行され、シェルスクリプトのように子プロセスを生成することはない。
「function」は省略することが出来る。

::: note info
unsetコマンドで解除することが可能
:::

### declareコマンド
**書式:declare [オプション] 名前**
変数を宣言したり、整数を格納する変数、トレース可能な関数など、変数や関数に属性を与えることが出来る。
setコマンド同様に、シェル内のすべてのシェル変数と環境変数および関数を表示させることも出来る。

| オプション | 説明 |
|:-:|:-:|
| -f  | 現在定義されている関数を全て表示する  |


## bashの設定ファイル

![キャプチャ3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3238179/2f325436-8d72-e0c6-225e-848458d18fa0.png)


| ファイル | 説明 |
|:-:|:-:|
| /etc/profile  | 環境変数、利用環境に関わるもの。ログイン時に実行され、全ユーザーから参照される  |
| /etc/bash.bashrc  | Debian系でbash起動時に実行させたい処理。全ユーザーから参照される  |
| /etc/bashrc  | RedHat系でbash起動時に実行させたい処理。`~/.bashrc`から参照される。全ユーザー対象  |
| ~/.bash_profile  | ログイン時に実行されるユーザー独自でカスタマイズ可能。読み取り権限が必要、実行権は必要ない。  |
| ~/.bash_login  | `~/.bash_profile`がない場合、ログイン時に実行される。内容は`~/.bash_profile`と一緒。  |
| ~/.profile  | `~/.bash_profile`、`~/.bash_login`もない場合、ログイン時に実行される。内容は`~/.bash_profile`と一緒。  |
| ~/.bashrc  | bash起動時に実行される。対話型シェルが起動されるたびに実行される。自分用にコマンドのエイリアスを設定したい時に編集するファイルでもある。  |
| ~/.bash_logout  | ログアウト直前に実行されるスクリプトで、ログアウト前に行いたい処理を記述する  |

### 設定ファイルの実行順序
bashはログインシェルとして起動すると、`/etc/profile`、`~/.bash_ profile`、`~/.bash_ login`、`~/.profile` の順番で各ファイルを読み込ん で実行する。


![キャプチャ2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3238179/f12944cc-6c49-beb3-bd7c-4847c8ad298c.png)

# シェルスクリプト
シェルにはスクリプト言語によるプログラミング機能が備わっている。使うことにより、一連のコマンドライン作業を自動化することが出来る。テキストファイルにコマンドを記述するだけで作成することが可能

実行方法はいくつかある。スクリプトファイルに実行権限を追加すると実行することが出来るようになる。
4つ目の方法ではコマンドと同じようにシェルスクリプトを実行するため、シェルスクリプトが配置されているディレクトリにパスが通っていない（環境変数PATHに含まれていない）場合はパスを指定する必要がある。
~~~ md
#実行方法
$ bash スクリプトファイル名
$ source スクリプトファイル名
$ . スクリプトファイル名
$ ./スクリプトファイル名
~~~

特殊な変数を用いて引数を参照することも出来る

| 変数名 | 説明 |
|:-:|:-:|
| $$  | シェルのPID  |
| $0  | シェルスクリプトファイル名(フルパス)  |
| $1  | 1番目の引数  |
| $2  | 2番目の引数。以下順に$3,$4・・$nとなる。10個目以降は「${10}」のように指定する。  |
| $#  | 引数の数  |
| $@  | 全ての引数(スペース区切り)  |
| $*  | 全ての引数(区切りは環境変数IFSで指定されたもの)  |
| $?  | シェル対して戻り値を返す。正常終了であれば0、しなかった場合は0以外の値が返される |


#### shebang(シバン)
シェルスクリプトは、シェルの種類によって異なる。ファイルの1行目は#!で始まり、その後にプログラムを解釈実行するインタープリタのパスを書く。

::: note info
**・インタプリタ（interpreter）とは？？**
人間が書いたコードをコンピュータが理解できるように1行ずつ翻訳しながら実行するプログラムのこと。日本語で「通訳者」という意味。
:::


| インタープリタ | 1行目の記述 |
|:-:|:-:|
| bash  | #!/bin/bash  |
| perl  | #!/usr/bin/perl  |
| python  | #!/usr/bin/python  |

スクリプトをコマンドとして実行した場合は、#!の次に書かれたコマンドがスクリプトを解釈実行するインタープリターとなる。

![キャプチャ4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3238179/565f5e63-967f-0df2-20b0-df2d8041b773.png)

`#!/bin/sh`に関して詳しい記事をコメントでくださったので以下に記載しておきます。POSIX準拠された動きをするシェルみたい。。

[シェルスクリプトの1行目に書くおまじないで使える便利オプション集](https://qiita.com/yn-misaki/items/6fcfab082dd664f10d4e)


### execコマンド
**書式:exec コマンド**
シェルスクリプトを実施しているシェルプロセスが、指定したコマンドのプロセスに置き換わる。

### testコマンド
**書式:test 条件文**
**書式：[ 条件文 ]**
条件文に書かれた式を評価し、真(条件が満たされる)なら0、偽(条件が満たされない)なら0以外の値を返す

+ **ファイル形式のテスト**

| 条件式 | 実行結果 |
|:-:|:-:|
| -f ファイル | ディレクトリを除くファイルがあれば真  |
| -d ディレクトリ | ディレクトリがあれば真  |
| -r ファイル | ファイルが存在し、かつ読み込み可能であれば真  |
| -w ファイル | ファイルが存在し、かつ書き込み可能であれば真  |
| -x ファイル | ファイルが存在し、かつ実行可能であれば真  |
| -s ファイル | サイズが0より大きいファイルがあれば真  |
| -L ファイル | シンボリックリンクであるファイルがあれば真  |

+ **ファイル特性のテスト**

| 条件式 | 実行結果 |
|:-:|:-:|
| -e ファイル  | ファイルがあれば真  |
| ファイル1 -nt ファイル2  | newer thanの意味。ファイル1がファイル2より修正時刻が新しければ真  |
| ファイル1 -ot ファイル2  | older thanの意味。ファイル1がファイル2より修正時刻が古ければ真  |

+ **数値のテスト**

| 条件式 | 実行結果 |
|:-:|:-:|
| 数値1 -eq(equal) 数値2  | 数値1と数値2が等しければ真  |
| 数値1 -ge 数値2  | greater than or equal toの意味。数値1と数値2より大きい、もしくは等しければ真  |
| 数値1 -gt 数値2  | greater thanの意味。数値1と数値2より大きければ真  |
| 数値1 -le 数値2  | less than or equal toの意味数値1と数値2より小さい、もしくは等しければ真  |
| 数値1 -lt 数値2  | less thanの意味数値1と数値2未満であれば真  |
| 数値1 -ne 数値2  | not equalの意味。数値1と数値2が等しくなければ真  |

+ **文字列のテスト**

| 条件式 | 実行結果 |
|:-:|:-:|
| -n 文字列  | 文字列の長さが0より大きければ真  |
| -z 文字列  | 文字列の長さが0であれば真  |
| 文字列1 = 文字列2  | 2つの文字列が等しければ真  |
| 文字列1 != 文字列2  | 2つの文字列が等しくなければ真  |

+ **テストの論理結合**

| 条件式 | 実行結果 |
|:-:|:-:|
| !条件  | 条件式が偽であれば真  |
| 条件1 -a 条件2  | 両方の条件式が真であれば真(and)  |
| 条件1 -o 条件2  | いずれかの条件式が真であれば真(or)  |

::: note info
コマンドが終了値として返す値はそれぞれのコマンドの中で指定されている。コマンドの返り値はmanコマンドで調べることが出来る
:::

## スクリプトの実行方法
実行するにはいくつか方法が存在する

### bash、shコマンド
**書式：bash シェルスクリプトファイル名**
シェルを起動してシェルスクリプトを実行するコマンド。シェルスクリプトに実行権が無い場合でも実行できる。実行するシェルスクリプトに読み取り権と、シェルスクリプトが存在するディレクトリに検索権が必要。

+ **PS1(デフォルト:`\s-\v\$`)**:コマンドプロンプト
+ **PS2(デフォルト:`>`)**：コマンドラインが完了せず、継続行である

| 主な表記 | 説明 |
|:-:|:-:|
| \s  | シェルの名前  |
| \v  | bashのバージョン  |
| \u  | ユーザー名  |
| \h  | ホスト名のうちの最初の.まで  |
| \w  | 現在の作業ディレクトリ  |


### sourceコマンド
**書式：source シェルスクリプトファイル名**
指定したシェルスクリプトを読み込み、現在のシェルで実行するコマンド。実行権が無い場合でも実行可能。ただし、実行するシェルスクリプトに読み取り権と、シェルスクリプトが存在するディレクトリに検索権が必要。

### コマンドとして実行
**書式：. /シェルスクリプトファイル名**
シェルスクリプトに実行権を設定し、シェルスクリプトのパスを指定する方法。ただし、パスが通っていない場合は、絶対パスまたは相対パスでシェルスクリプトを指定する必要がある。
シェルスクリプトはサブシェル(現在のシェルから新たに生成されたシェル)内で実行される。


### コマンドの置換機能
コマンドの実行結果を文字列として扱うことができる。

+ `実行コマンド`(バッククォートで囲む)
+ $(実行コマンド)

~~~ md
$ls
dir1 dir2 test1.txt test2.txt

RESULT=$(ls)
RESULT=`ls`

$echo $RESULT
dir1 dir2 test1.txt test2.txt
~~~


## 制御実行

### if文
~~~ md
#書式
if 条件式
then
    実行文1
else
    実行文2
fi
~~~
条件によって処理を分岐したり、繰り返し処理を行うためのコマンド。条件式が真の場合実行文1が実行され、偽の場合実行文2が実行される。

~~~ md
#testscriptというファイルがあれば実行し、なければファイルが存在しない
if test -f testscript
then
    source ./testscript
else
    echo "testscript file not exist"
fi
~~~

### case文
式の値に応じて複数に分岐するのに有効。値は増やすことが出来る。
~~~ md
#書式
case 式in
    値1）
      実行文1 ;;
    値2)
      実行文2 ;;
    :
    :
esac
~~~

### for文
繰り返し処理を行う場合に有効。**seqコマンド**を利用すると、連続した数値を自動的に生成することが出来る。
~~~ md
#書式
for 変数名 in 変数に代入する値のリスト
do
    実行文
done

# 変数iに10~15までの連続した数値を代入する
for i in `seq 10 15`
do 
    echo $i
done
~~~

### while文
条件式が満たされている間、doとdoneの間の実行文を実行する
~~~ md
#書式
while 条件式
do
    実行文
done

#変数iの値が10になるまで繰り返す
i=1
while [ $i -le 10]
do
    echo $i
    let i=i+1
done
~~~

### readコマンド
**書式：read 変数**
標準入力から、またはリダイレクションによるテキストファイルなどから改行またはEOF（End Of File: ファイルの終了）までのデータを読み取り、それを変数に格納する。

読み込んだデータは以下のように格納される
+ 変数名指定が1つの場合、受け取ったすべてのデータを指定された変数に格納する
+ 変数名指定が複数の場合、受け取ったデータをスペースまたはタブで分割し、順に変数に格納していく
+ 指定した変数の数より分割したデータのほうが多い場合、最後の変数に残り全てのデータが格納される
    + 指定した変数の数より分割したデータのほうが少ない場合、データの割り当てられなかった変数には空の値が設定される（データのない変数が作成される）

| オプション | 説明 |
|:-:|:-:|
| -p 文字列  | 読み込む前に文字列を表する  |



### seq(sequence)コマンド
**書式:seq 終了値**
**書式:seq 初期値 終了値**
**書式:seq 初期値 増分 終了値**
引数として整数値を1つ指定するとそれを終了値とし、開始値1から終了値までを+1しながら表示する。