#author("2020-03-16T06:13:34+00:00","default:mizutu","mizutu")
#author("2020-04-06T21:12:08+00:00","default:mizutu","mizutu")
[[私的AI研究会]] > Shell覚書

* ShellScript覚書 [#i50e21b4]
#contents

** 「Hello,World!!」 [#aeaee703]
- シェルスクリプトではlinuxコマンドであるのもは使えるので、出力をechoコマンドで行うことができる。
 $ vi hello.sh 
 
 #!/bin/sh
 
 echo "Hello,World!!"
- できたファイルbのパーミッションを実行可能にする
 $ chmod u+x hello.sh
- シェルスクリプトを実行
 $ ./hello.sh
 Hello,World!!
-- hello.shの一行目 「#!/bin/sh」はシェル s hのパスを書く
-- bashの独自機能を利用したい場合は「#!/bin/bash」

- シェルスクリプトでは文字列を””でくくる必要は無いのでhello.shは以下のようにも書ける
 #!/bin/sh
 
 echo Hello,World!!

** 変数 [#id68ee0b]
- シェルスクリプトにはプログラミング言語と同じように変数を宣言、定義できる
- シェルスクリプトの変数はpythonの変数に近い

** シェル変数 [#kb01ad49]
- シェルスクリプト内での変数をシェル変数といい、"="で利用できる
 $ vi sample.sh 
 #!/bin/sh
 
 val1="Hello,World!!"
 val2=20
 
 echo val1
 echo "age:${val2}"
- 変数の利用は=で行い、文字列と変数を繋げたい場合は「${変数名}」で連結できる

** 引数 [#p948c217]
- 他のコマンドと同様にシェルスクリプトにも引数を渡すことができる
 $ vi catn.sh 
 #!/bin/sh
 
 cat -n $1
- n番目の引数を呼び出すには「$n」とする
 $ ./catn.sh sample.sh
   |   $0  | |  $1   |
- $0はシェルスクリプト名になりその後は順に数値が増えていく
- 引数を扱えるものなどを特殊変数という
#br

*** 特殊変数 [#ye53eacf]
>
|特殊変数|意味|h
|$0|シェルスクリプトの名前|
|$n|n番目の引数|
|$*|すべての引数リスト|
|$#|与えられた引数の数|
|$?|直前に実行したコマンドの戻り値|
|$$|シェルスクリプトが実行された際のPID|
|$LINENO|この変数を記述した行番号|

** 条件分岐 [#n37b8518]
*** if [#i34ab602]
- シェルスクリプトで条件分岐を行うときはif文を使用する
 $ vi sample_if.sh 
 #!/bin/sh
 
 if [ $1 = hello ]
 then
     echo arg is hello
 elif [ $1 = world ]
 then
     echo arg is world
 else
     echo arg is neither hello nor world
 fi
- if 文は[]内に条件を入れ then をつける
- 複数の条件を扱うときは elif でつなぎ if 同様 then でつなぐ、else はそのまま使用し
条件分岐の終わりは fi で閉じる

*** test [#e061d9f6]
- if 文において条件判定に[]ではなく真偽を判定する test コマンドを使用することができる
 $ vi sample_test.sh 
 #!/bin/sh
 
 if test -f $1; then
     echo File $1 exists
 fi

*** case [#u8865175]
- switch~case 文の記述
 $ vi sample_case.sh 
 #!/bin/sh
 
 case $1 in
     hello) echo hello ;;
     world) echo world ;;
     *) echo other ;;
 esac
- case の後に判定したい変数などを指定し、その後に「条件)」の形で判定していく
- *)は switch~case 文の default
- 末尾に;;を忘れないこと

*** testコマンド オプション [#v421a7d4]
- 文字列
|オプション|意味|h
|-n string|文字列の長さが0でないなら真|
|-z string|文字列の長さが0なら真|
|string1 = string2|同一なら真|
|string1 != string2|同一でないなら真|

- 数値
|オプション|意味|h
|num1 -eq num2|等しいなら真|
|num1 -ne num2|等しくないなら真|
|num1 -gt num2|num1がnum2より大きいなら真|
|num1 -ge num2|num1がnum2以上なら真|
|num1 -lt num2|num1がnum2より小さいなら真|
|num1 -le num2|num1がnum2以下なら真|

- ファイル
|オプション|意味|h
|-f file|fileが存在し、通常ファイルなら真|
|-c file|fileが存在し、キャラクタスペシャルファイルなら真|
|-e file|fileが存在すれば種類によらず真|
|-d file|fileが存在し、ディレクトリなら真|
|-L file|fileが存在し、シンボリックなら真|
|-r file|fileが存在し、読み取り可能なら真|
|-w file|fileが存在し、書き込み可能なら真|
|-x file|fileが存在し、実行可能なら真|

- 複合式
|オプション|意味|h
|expr1 -a expr2|2つの式の論理積をとる|
|expr1 -o expr2|2つの式の論理和をとる|
|!expr|式の否定を返す|

** ループ [#j1a51e5b]
*** for [#ge6a9f18]
- 単純ループ for
 $ vi sample_for.sh 
 #!/bin/sh
 
 for str in hello world shell; do
     echo $str
 done
for 文は「for 変数名 in 文字列1 文字列2 .... ; do ~ done」と記述する

*** seq [#ka33e291]
- python での range 関数に相当し、「seq 第一引数 第二引数」と記述することで
第一引数以上第二引数以下の整数を順番にループする
 #!/bin/sh
 
 for number in `seq 1 3`; do
     echo "${number}"
 done
このコードでは1,2,3とループされる~
&color(red){seqコマンドを囲んでいるのが「''(シングルクォート)」ではなく「``(バッククォート)」であることに注意};

*** while [#v05616c9]
- for文は一定の回数ループ処理を行いたいときに使用、回数不明の時には while 文を使用する~
回数がわかりにくい例としてフィボナッチ数列を実装
 sample_while.sh 
 #!/bin/sh
 
 max=40
 a=1
 b=1
 
 while [ $b -le $max ]; do
     echo $b
 
     a=`expr $a + $b`
     b=`expr $a - $b`
 
 done
> このシェルスクリプトでは変数 max 以下のフィボナッチ数列を計算している~
このように回数がわからないがループ処理をしたいときには while 文が有効

*** expr [#e64631c8]
- while の例で「expr num1 演算子 num2」とすればnum1とnum2に演算を適用し、その結果を返してくれる

** 関数を使用する [#neede416]
- シェルスクリプトではいくつかの処理を一つの関数としてまとめることができる
 #!/bin/sh
 
 func(){
     echo $1 + $2 = `expr $1 + $2`
 }
 
 x=10
 y=2
 
 func $x $y
「関数名(){ 処理 }」という形で関数は実現され、シェルスクリプトに引数を渡すように関数にも渡すことができる

#br

** 参考資料 [#sa5e6dab]
- [[Linux初心者のシェルスクリプト入門>+https://qiita.com/lrf141/items/6c01d2f7afff79cd7286]]
- [[シェルスクリプトBash入門>+https://qiita.com/ebisennet/items/573618ab827ce1660b0e]]

#br