こんにちはフロントエンドエンジニアのまさにょんです!
今回は、ShellScriptの基本文法 (変数, 日付, 演算, 条件分岐, ループ処理)についてまとめて解説していきます。
目次
- 1 ShellScriptの基本文法まとめ (変数, 日付, 演算, 条件分岐, ループ処理など)
- 1.1 ShellScriptファイルの実行
- 1.2 ShellScriptファイルの実行権限を解放する
- 1.3 標準出力
- 1.4 変数にデータを格納する & 変数を展開する
- 1.5 バック・クオーテーションは、コマンドが実行できる
- 1.6 定数の定義
- 1.7 文字列の連結
- 1.8 四則演算
- 1.9 配列の取り扱い
- 1.10 日付・時間の操作
- 1.11 条件式の評価の基本ルール
- 1.12 数値の比較演算子
- 1.13 文字列の比較演算子
- 1.14 ファイルの比較演算子
- 1.15 論理演算子
- 1.16 条件分岐・if文
- 1.17 条件分岐・case文
- 1.18 while文
- 1.19 continue文・break文
- 1.20 for文
- 1.21 コマンド引数の使い方
- 1.22 ユーザーからの入力を受け付る
- 1.23 選択肢(option)から選ばせる
- 1.24 ファイルから入力する
- 1.25 関数の作成
- 2 関連記事
- 3 プログラミング学習・エンジニア転職関連の情報
- 4 Twitterやってます!Follow Me!
- 5 Linux関連書籍
- 6 参考・引用
- 7 最近の投稿
ShellScriptの基本文法まとめ (変数, 日付, 演算, 条件分岐, ループ処理など)
ShellScriptファイルの実行
ShellScriptファイルの実行方法は、絶対パス or 相対パス で ShellScriptファイルにアクセスするだけです。
作業ディレクトリで、次の一文だけの sample.sh ファイルを作成します。
ちなみに、拡張子shは、ShellScriptのファイルであることを示します。
echo 'Hello Robotama'
作成した sample.sh ファイルを実行する場合は、次のようにします。
# 相対パスで指定して、ShellScriptファイルを実行する
./sample.sh
ShellScriptファイルの実行権限を解放する
ShellScriptファイルを実行しようとして、次のようなエラーがでる場合は、Permission設定を変える必要があります。
zsh: permission denied: ./sample.sh
実行権限だけの解放は、次のようにすればOKです。
chmod +x sample.sh
Permission設定に関する細かい説明は、以前の記事にて解説しています。
標準出力
Linuxコマンド、ShellScript での標準出力には、echoコマンドを使用します。
echo 'Hello World'
# Hello World
echo コマンドに関する細かい使い方は、以前の記事にて解説しています。
変数にデータを格納する & 変数を展開する
変数にデータを格納する際は 、変数名=値 と記述します。
「 = 」の前後にスペースを入れてはいけないので注意です。
変数を展開・使用する際は、$変数名 や “$変数名” 、“${変数名}”とします。
また、ダブル・クオーテーションではなく、シングル・クオーテーションにすると変数展開ができないので注意です。
## 1. 変数にデータを格納する => 「 = 」の前後にスペースを入れてはいけない
robotama="ロボ玉"
## 2. 変数からデータを取り出す
echo $robotama
# ロボ玉
echo "$robotama"
# ロボ玉
echo "${robotama}"
# ロボ玉
## 3. 変数の中身ではなく文字列として表示されてしまうので注意!
echo '$robotama'
# $robotama
バック・クオーテーションは、コマンドが実行できる
シングル・クオーテーションは、すべてを文字列として取り扱い、ダブル・クオーテーションは、変数だけは展開してくれます。
コマンドを展開・実行してもらいたい時は、バック・クオーテーションを使用すると変数およびコマンドを展開・実行してくれます。
robotama=ロボ玉
# 1. シングル・クオーテーションは、すべてを文字列として取り扱う!
echo 'echo $robotama'
# 2. ダブル・クオーテーションは、変数だけは展開する!
echo "echo $robotama"
# 3. バック・クオーテーションは、変数を展開するだけでなく、コマンドも実行できる!
echo `echo $robotama`
### 実行結果 ###
# echo $robotama
# echo ロボ玉
# ロボ玉
定数の定義
定数(読み取り専用)を定義する場合は、readonly を変数名の前に付与します。
## 1. 定数(読み取り専用)を定義する
readonly gunmar='神聖グンマー帝国'
echo ${gunmar}
# 神聖グンマー帝国
## 2. 定数なので、再代入しようとするとエラーがでる
gunmar=ゴンさん
# [エラー] gunmar: readonly variable
文字列の連結
文字列の連結には、「 + 」などの記号は必要ありません。
ただ、並べるだけで連結されます。
echo 'ゴンさん'
# ゴンさん
## 1. 文字列の連結
echo 'Hunter'' × ''Hunter'
# Hunter × Hunter
robotama="ロボ玉"
echo $robotama' × '$robotama
# ロボ玉 × ロボ玉
echo "$robotama And $robotama"
# ロボ玉 And ロボ玉
echo "${robotama}は、グンマー帝国出身です"
# ロボ玉は、グンマー帝国出身です
四則演算
expr コマンドによる計算は書き方が面倒なので、数値計算には、 $(( … )) を使用するのがオススメです。
ちなみに似たような機能で let コマンドや ((…)) がありますが、どの環境でも使えるのは $((…)) だけです。
bash だけではなく、すべての POSIX 準拠のシェルで使うことができる点で考えても、 $(( … )) を使った方がよさそうです。
x=10
## 1. 通常、数値を格納しても文字列として取り扱われる。
echo $x+2
# 10+2
## 2. 数値を計算する場合は、$((計算式))と記述する
echo $(($x+2))
# 12
echo $((($x+5) * 2))
# 30
配列の取り扱い
ShellScriptでは、()と半角スペースで配列を定義します。
配列の中の特定の要素を取り出すには、${配列名[index]} で取り出します。
配列の中身をすべて取り出すには、${配列名[@]} とします。
また、${#配列名[@]} で、配列の長さ・要素数を取得することができます。
### 配列の定義 ###
## 1. ()と半角スペースで配列を定義する
array=(2 4 6)
### 配列のデータを取得する ###
## 2. 配列名だけで変数展開すると最初の要素が表示される
echo $array
# 2
## 3. 指定して中身を取り出すには、${配列名[index]} で取り出す
echo ${array[0]}
# 2
## 3. 指定して中身を取り出すには、${配列名[index]} で取り出す
echo ${array[1]}
# 4
# 4. ${} で変数展開しないと、最初の要素と文字列を連結した文字列になる・・・
echo $array[1]
# 2[1]
## 5. 配列の中身をすべて取り出すには、${配列名[@]} とする
echo ${array[@]}
# 2 4 6
## 6. ${#配列名[@]} で、配列の長さ・要素数を取得することができる
echo ${#array[@]}
# 3
### 配列にデータを追加する ###
## 7. 配列の指定Indexに値を代入する
array[2]=10
echo ${array[@]}
# 2 4 10
## 7. 配列の指定Indexに値を代入する
array[3]=20
echo ${array[@]}
# 2 4 10 20
## 8. 配列に値を、まとめて追加する
array+=(30 40)
echo ${array[@]}
# 2 4 10 20 30 40
日付・時間の操作
Linuxでの日付・時間の操作は、dateコマンドを使います。
ちなみに、Macのdateコマンドは、使い方が違うので注意です。詳細は、次の記事を参照。
【備忘録】macのdateコマンド(BSD系)で日付を出力、計算する
##### 日付の取得・操作 #####
# 1. 今日の日時情報
date
# 2023年 1月12日 木曜日 07時40分28秒 JST
# 2. `date`は日付や曜日を要素とした配列になっている。
d=(`date`)
echo $d
# 2023年 1月12日 木曜日 07時40分28秒 JST
echo ${d[@]}
# 2023年 1月12日 木曜日 07時40分28秒 JST
# 3. ループで取り出す。
for i in ${d[@]}
do
echo $i
done
## 出力結果 ##
# 2023年
# 1月12日
# 木曜日
# 07時26分30秒
# JST
### 過去・未来の日時を取得する ###
# 2日前の日付を取得する
date -d '2 days ago'
# 現在の月を取得する
date '+%m'
# 10
# Nヶ月前の月を取得する
date -d "`date '+%Y-%m-01'` 1 months ago" '+%m'
# 現在日時から10秒前の日時を求める
date -d '10 seconds ago'
# 現在日時から10秒後の日時を求める
date -d '10 seconds'
# 現在日時から10分前の日時を求める
date -d '10 minutes ago'
# 現在日時から10分後の日時を求める
date -d '10 minutes'
# 現在日時から10時間前の日時を求める
date -d '10 hours ago'
# 現在日時から10時間後の日時を求める
date -d '10 hours'
# 現在日時から10日前の日時を求める
date -d '10 days ago'
# 現在日時から10日後の日時を求める
date -d '10 days'
# 現在日時から10ヶ月前の日時を求める
date -d '10 months ago'
# 現在日時から10ヶ月後の日時を求める
date -d '10 months'
# 現在日時から10年前の日時を求める
date -d '10 years ago'
# 現在日時から10年後の日時を求める
date -d '10 years'
### 日付のフォーマットを指定して実行する ###
# 上記のコマンドはそれぞれフォーマットを指定して実行することも可能
date -d '12 hours ago' '+%Y-%m-%d [%H:%M:%S]'
### 指定した日時で実行する ###
# date コマンドで表示される日時を現在日時ではなく、
# 次のように指定した日時で date コマンドを実行することも可能である。
# 現在日時を「2006/01/01 12:13:14」としてコマンドを実行する
date -d '2006/01/01 12:13:14'
# フォーマットの指定も可能
date -d '2006/01/01 12:13:14' '+%Y %m %d - %H %M %S'
条件式の評価の基本ルール
- 正常終了は0が返ってくる。異常終了は1が返ってくる。
- testコマンドで条件式を評価できる(testコマンドは
[]
で置き換え可能) $?
で、直前に終了した命令が正常終了したかどうかを評価できる
数値の比較演算子
- -eq : equal
- -ne : not equal
- -gt : greater than (◯◯より大きい)
- -ge : greater than or equal (◯◯以上)
- -lt : less than (◯◯より小さい)
- -le : less than or equal (◯◯以下)
## 比較演算子 ##
# 1. testコマンド or [ ] で、条件式を記述する
# 2. $? => 0は正常(true)/1は異常(false)
test 1 -eq 2
echo $?
# 1
# testコマンドではなく、[] を使っても条件式を記述することができる。
[ 1 -eq 2 ]
echo $?
# 1
test 1 -eq 1
echo $?
# 0
# 「 ; 」区切りで、インラインで(1行で)実行できる
test 1 -eq 2; echo $?
# 1
test 1 -eq 1; echo $?
# 0
文字列の比較演算子
- = : equal
- != : not equal
[ robotama = robotama ]
echo $?
# 0
[ robotama != robotama ]
echo $?
# 1
ファイルの比較演算子
- -nt : newer than(より新しいかどうか)
- -ot : older than(より古いかどうか)
- -e : exist (存在しているかどうか)
- -d : directory (ディレクトリかどうか)
ShellScript-関連 % ls -l
total 40
-rwxr-xr-x 1 robotama staff 270 1 9 16:14 Gunmar.sh
-rwxr-xr-x 1 robotama staff 429 1 12 07:54 Puru.sh
-rwxrwxrwx 1 robotama staff 6246 1 12 08:00 robotama.sh
-rwxrwxrwx 1 robotama staff 2 1 12 22:25 sample.sh
test Gunmar.sh -nt robotama.sh; echo $?
# 1
test Gunmar.sh -ot Puru.sh; echo $?
# 0
test -e Gunmar.sh; echo $?
# 0
[ -d Puru.sh ]; echo $?
# 1
論理演算子
- -a : and
- -o : or
- ! : is not
# ファイルが存在するかどうか
test -e hello.sh -o -e Gunmar.sh; echo $?
# 1
# 1 = 1 && 2 == 2
test 1 -eq 1 -a 2 -eq 2; echo $?
# 0
# 5 != 5
test ! 5 -eq 5; echo $?
# 1
条件分岐・if文
### 条件分岐・if文 ###
x=21
if [ $x -ge 60 ]
then
echo "60以上の数値 (greater than or equal 60 : 60以上)"
elif [ $x -ge 40 ]
then
echo "40以上の数値 (greater than or equal 40 : 40以上)"
elif [ $x -ge 20 ]
then
echo "20以上の数値 (greater than or equal 20 : 20以上)"
else
echo "19以下の数値"
fi
echo "必ず呼び出される finally処理"
## 実行結果 ##
# 20以上の数値 (greater than or equal 20 : 20以上)
# 必ず呼び出される finally処理
条件分岐・case文
- caseの値に合致したときに処理は ) から ;; まで実行する
- 何にも当てはまらない時の条件は *) で指定する
signal="red"
case $signal in
"red")
echo "stop!"
;;
"yellow")
echo "caution!"
;;
"green")
echo "go!"
;;
*)
echo "..."
;;
esac
## 実行結果 ##
# stop!
while文
条件式の間だけdoとdoneの間の処理をする。
i=0
while [ $i -lt 12 ]
do
i=`expr $i + 1`
echo $i
done
continue文・break文
i=0
# :を使うと常に0(正常終了)を返すので、無限ループになる
while :
do
i=$(($i + 1))
# 3 <= $i <= 10 の時は、何も処理せずにループ続行する
if [ $i -ge 3 -a $i -le 10 ]; then
continue
fi
# $iが13以上になったらループ終了
if [ $i -ge 13 ]; then
break
fi
echo $i
done
## 実行結果 ##
# 1
# 2
# 11
# 12
for文
inに続くスペース区切りの値を入れていきdoとdoneの間の処理を実行
for i in 1 2 3 4 5
do
echo $i
done
# 配列を使いたい時
a=(1 2 3 4 5)
for i in ${a[@]}
do
echo $i
done
# continue文・break文の使い方は、while文と同様
numList=(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)
for i in ${numList[@]}
do
if [ $i -ge 3 -a $i -le 10 ]; then
continue
fi
# $iが13以上になったらループ終了
if [ $i -ge 13 ]; then
break
fi
echo $i
done
コマンド引数の使い方
sample.shファイルを次の内容で作成する
# ファイル名
echo $0
# 1番目の引数
echo $1
# 2番めの引数
echo $2
# 全ての引数
echo $@
# 引数の数
echo $#
./sample.sh フィルに引数を渡して、実行する
# 1. sample.shファイルに3つ引数を渡して、実行する
./sample.sh robotama purupuru nanoda
### 実行結果 ###
./sample.sh
robotama
purupuru
robotama purupuru nanoda
3
ユーザーからの入力を受け付る
readコマンドを使って、ユーザーが入力した値を変数に格納できます。
入力 & Enterを待機するので、入力内容に応じた処理ができます。
keyという変数にユーザーの入力した値を入れて処理しています。
# 「 while : 」は永続true => 無限ループ
while :
do
# readコマンドを使って、ユーザーが入力した情報を変数に格納する => 入力 & Enterを待機する
read key
echo "you pressed $key"
# 「 end 」と入力した時だけ、終了する(無限ループから抜け出す)
if [ $key = "end" ]; then
break
fi
done
sample.sh ファイルを実行して、入力 & Enterを繰り返す。
./sample.sh
robotama
you pressed robotama
purupuru
you pressed purupuru
gunmar
you pressed gunmar
end
you pressed end
選択肢(option)から選ばせる
select というコマンドを使用することで、選択肢から選ばせることができる。
select option in Gunma Saitama Tokyo
do
echo "you from $option"
break;
done
sample.sh ファイルを実行して、Gunmaを選択する。
./sample.sh
1) Gunma
2) Saitama
3) Tokyo
#? 1
you from Gunma
ファイルから入力する
ロボ玉試作1号機
ロボ玉試作2号機
ロボ玉試作3号機
i=1
# 変数lineに1行ずつ格納される
while read line
do
echo "$i: $line"
i=$(($i + 1))
# ここで読み込むファイルを指定(引数)
done < $1
./sample.sh Robotama.txt
## 実行結果 ##
1: ロボ玉試作1号機
2: ロボ玉試作2号機
3: ロボ玉試作3号機
関数の作成
関数内で作った変数は関数外でも使用できる。ローカル変数にしたい場合は local i=12 みたいにlocalを使用する。
# functionは省略可能
function JoJo () {
echo "$1・$2、みんな JoJoって呼ぶんだ"
i=12
echo "好きな数字は${i}"
}
# 関数を実行する
JoJo ジョニー ジョコビッチ
## 実行結果 ##
ジョニー・ジョコビッチ、みんな JoJoって呼ぶんだ
好きな数字は12
関連記事
プログラミング学習・エンジニア転職関連の情報
自宅で現役エンジニアから学べる『TechAcademy』 (エンジニア転職保証)
『GEEK JOBキャンプ』スピード転職コース(無料)
【IT道場】入校時0円! 就職目的プログラミングスクール
エンジニア転職なら100%「自社開発」求人に強い【クラウドリンク】
『techgym』 (Python特化・無料)
Twitterやってます!Follow Me!
神聖グンマー帝国の逆襲🔥
神聖グンマー帝国の科学は、世界一ぃぃぃぃぃぃ!!!!!
Linux関連書籍
参考・引用
- シェルスクリプトの基礎知識まとめ
- 今どきのシェルスクリプトは数値計算にexprを使わない(POSIX準拠)
- 日付を取得する | UNIX & Linux コマンド・シェルスクリプトリファレンス
- 【Linux】echoコマンドの使用方法