お勉強メモを整理します。
(個人的にまとめていたものなので一部出典が不明です、すみません、、)
基本知識
そもそも
シェル:オペレーティングシステム(OS)と対話するためのインターフェース
→ コマンドなどを制御する環境
(https://eng-entrance.com/linux-shellscript-what)
シェルスクリプト:シェルが解釈できるコマンドをまとめて実行できるようにドキュメントにしたもの(Unixコマンドなど)
→ Linuxのターミナル操作に通ずるものがある?
・「いつ」「何の条件で」「何の命令をする」
・ファイルコンテンツを読み込む
・ログファイルを書き出す
などの制御が可能
☆ シェルスクリプトはインタプリタ
記述内容の上から順に、【コマンド → 制御文 → 変数など】を解釈しながら実行する
=コンパイルがないのですぐに実行結果がわかる
お約束
・拡張子:.sh
・最初の1行目:#!/bin/sh
(シェバング、シバン)
システムに「この下はシェルスクリプトを書いています」と知らせる
※ bash独自の機能を使う場合は#!/bin/bash
と書く
・文末に;
(セミコロン)はいらない
#!/bin/sh
echo "Hello, World!"
対象のシェルスクリプトファイルはsh(またはbash) ファイル名
で実行
$ sh example.sh
$ Hello, World!
基本処理
1. コメント
#!/bin/sh
# コメント
# 実行されない
2. 入力・出力
read NAME # 入力
echo "Hello, ${NAME}!" # 出力
Taro
Hello, Taro!
3. 変数
<条件>
・ 使える文字・・・a~z(小文字)、A~Z(大文字)、0~9(数字)、_(アンダースコア)
・ 先頭文字に数字は不可
・ =
の前後には空白なし
・ 変数のアクセスは単体の場合$変数
、文字の連結などがある場合${変数}
→ ${変数}
を使用しておけば間違いない?
var="これは変数です"
Var_2="これも変数"
echo "Var_2=${Var_2}" # 結果:「Var_2=これも変数」
# 変数を上書き不可
readonly var # 上書きするとエラー
# 変数削除(readonly変数は不可)
unset Var_2
☆ 特殊な変数
変数 | 内容 | 結果例 |
---|---|---|
$0 | スクリプト名 | echo $0 → script.sh |
\$1 ~ $9 | シェル引数 | |
$# | シェル引数の数 | echo $# → 3(引数3つ) |
$* | 全引数のリスト | echo "$*" → "first second third" |
$@ | 全引数のリスト(個別) | echo "$@" → "first" "second" "third" |
$- | シェルの実行オプション(setコマンドや#!/bin/bash行に付けたオプション) | |
$? | 最後に実行したコマンドの終了値(戻り値) | echo $? → 0(成功)もしくは1(失敗) |
$$ | 実行中のシェルのプロセスID | |
$! | シェルが最後に実行したバックグラウンドプロセスID |
☆ 変数値の置換
方法 | |
---|---|
${var} | 変数へのアクセス |
${var:-word} | 中身チェック:空文字の場合wordを返す |
${var:=word} | 中身チェック:空文字の場合wordを返す varに文字列を保存する |
${var:?word} | 中身チェック:空文字の場合エラー |
${var:+word} | 中身チェック:空文字ではなかった場合wordを返す |
echo "1 - ${var:-wordSetInEcho1}"
echo "2 - var = ${var}"
echo "3 - ${var:=wordSetInEcho3}"
echo "4 - var = ${var}"
unset var
echo "5 - ${var:+wordSetInEcho5}"
echo "6 - var = $var"
var="newVarValue"
echo "7 - ${var:+wordSetInEcho7}"
echo "8 - var = $var"
echo "9 - ${var:?StandardErrorMesage}"
echo "10 - var = ${var}"
1 - wordSetInEcho1 # varは空なのでword~がそのまま返ってくる
2 - var = # varに保存されないため空のまま
3 - woedSetInEcho3 # varは空なのでword~がそのまま返ってくる
4 - var = wordSetInEcho3 # word~がvarに保存されている
(unset varにより変数削除)
5 - # varは空なのでword~が返ってこない
6 - var = # varに保存されないため空のまま
(var代入)
7 - wordSetInEcho7 # varにnew~が入っているためword~が返ってくる
8 - var = newVarValue # varに入っているnew~が出力される
9 - newVarValue # varにnew~が入っているため成功、そのまま出力される
10 - var = newVarValue # varに入っているnew~が出力される
4. 配列(Bash)
ARRAY=(item1 item2 item3 item4)
ARRAY[0]="ITEM1"
ARRAY[2]="ITEM3"
echo "ARRAY[0]: ${ARRAY[0]}"
echo "ARRAY[*]: ${ARRAY[*]}"
ARRAY[0]: ITEM1
ARRAY[*]: ITEM1 item2 ITEM3 item4
5. オペレータ
算術演算子:`expr 数字 演算子 数字`
演算子 | 例 |
---|---|
+ | echo `expr 10 + 20` => 30 |
- | echo `expr 20 - 10` =>10 |
\* | echo `expr 11 \* 11` => 121 |
/ | echo `expr 10 / 2` => 5 |
% | echo `expr 10 % 4` => 2 |
= | a=$b (bの値はaに保存される) |
== | [ "\$a" == "\$b ] (\$aと$bが同じ場合TRUEを返す) |
!= | [ "\$a" != "\$b ] (\$aと$bが同じでない場合TRUEを返す) |
比較(以下の時TRUE)
演算子 | 内容 | 意味 |
---|---|---|
-eq | [ "\$a" -eq "\$b" ] \$a = \$b | equal to |
-ne | [ "\$a" -ne "\$b" ] \$a ≠ \$b | not equal to |
-gt | [ "\$a" -gt "\$b" ] \$a > \$b | greater than |
-lt | [ "\$a" -lt "\$b" ] \$a < \$b | less than |
-ge | [ "\$a" -ge "\$b" ] \$a >= \$b | greater than or equal to |
-le | [ "\$a" -le "\$b" ] \$a <= \$b | less than or equal to |
! | [ ! "\$a" -gt "\$b" ] !(\$a > \$b) | |
-o | [ "\$a" -gt "\$b" -o "\$a" -lt "\$b" ] | or |
-a | [ "\$a" -gt 90 -a "\$a" -lt 100 ] | and |
-z | [ -z "\$a" ] \$aが何も指定していない | |
-n | [ -n "\$a" ] \$aが何かを指定している |
6. if条件
if [ 条件 ] then コマンド fi
if [ "$1" -gt "$2" ]
then
echo "1番目のが2番目より大きい"
elif [ "$1" -eq "$2" ]
then
echo "1番目と2番目は同じ"
else
echo "1番目のが2番目より小さい"
fi
$ ./example.sh 2 7
1番目のが2番目より小さい
$ ./example.sh 10 5
1番目の引数が2番目の引数より大きい
$ ./example.sh 9 9
1番目の引数と2番目の引数は同じです
7.switch条件
case 変数 in 条件・値) コマンド ;; esac
DRINK="coffee"
case "$DRINK" in
"beer") echo "ビールです"
;;
"juice") echo "ジュースです"
;;
"coffee") echo "コーヒーです"
;;
esac
コーヒーです
8. ループ
・while
:条件が合うときにループする
a=0
while [ $a -lt 5 ]
do
echo $a
a=`expr $a + 1`
done
0
1
2
3
4
・until
:条件が合うまでループする(whileの逆、条件があったら終了)
a=0
until [ ! $a -lt 5 ]
do
echo $a
a=`expr $a + 1`
done
0
1
2
3
4
・for
:条件・値が変数と合う場合、コマンドを実行する
for 変数 in 複数値・変数・範囲 do コマンド done
for var in 0 1 2 3 4
do
echo $var
done
0
1
2
3
4
(共通ルール)
break
:ループ終了
continue
:ループスキップ
9. 関数
#関数の指定
MyFunction() {
echo "関数のechoです"
}
MyParamFunc() {
echo "引数1:$1 引数2:$2"
}
#関数の呼び出し
MyFunction
MyParamFunc param1 param2
関数のechoです
引数1:param1 引数2:param2
10. ファイルチェック
条件として使う
オプション | 内容 |
---|---|
-a ファイル名 | ファイルが存在する |
-d ファイル名 | ファイル名がディレクトリである |
-e ファイル名 | ファイルが存在する |
-f ファイル名 | ファイルが存在し、且つ、通常のファイル |
-L ファイル名 | ファイルが存在し、且つ、シンボリックリンク |
-r ファイル名 | ファイルが存在し、読み取り可能 |
-s ファイル名 | ファイルが存在し、空ではない |
-S ファイル名 | ファイルがソケットである |
-w ファイル名 | ファイルが存在し、書き込み可能 |
-x ファイル名 | ファイルが存在し、実行可能(ディレクトリ→検索可能) |
ファイルA -nt ファイルB | ファイルAがファイルBより新しい |
ファイルA -ot ファイルB | ファイルAがファイルBより古い |
if [ ! -f /var/log/example.log ]; then
echo "file not found"
else
: # 何も処理を行わない
fi
/var/log/example.logがあればスルー
/var/log/example.logがなければ処理実行
発展
11. ファイル行数、ファイル名取得
wc -l
☆ 行数のみ取りたい場合
$ cat sample.txt | wc -l
$ wc -l sample.txt | cut -d " " -f 1
$ wc -l sample.txt | awk '{print $1}'
12. 文字列処理
sed -e
(Stream Editor)
処理内容は、置換処理や行の削除、選択などいろいろできて、オプション -e で指定する
・文字列置換
sed -e 's/変更前の文字列/変更後の文字列/g' ./data.txt > ./data-new.txt
・文字列の一括削除
sed -e 's/変更前の文字列//g' ./data.txt > ./data-new.txt
・2~4行目を削除
sed -e ‘2,4d’ data.txt> ./data-new.txt
13. ファイルの最終更新日を変更
touch ファイル名
“ファイルをいま保存した”ようにタイムスタンプを変更する