Shellスクリプト基礎知識(全11記事+1)
├─シェルスクリプトの基本事項!
├─変数と特殊変数について!
├─演算子「算術演算子」「比較演算子」について!
├─条件分岐「if」「case」について!
├─ループ処理「for」「while」について!
├─文字列置換「bash」「sed」について!
├─複数行のテキスト出力!ヒアドキュメントについて!
├─書式?戻り値?シェルスクリプト内の関数について!
├─シェルの組み込みコマンドについて!
├─クォートとは?コマンド置換とは?実現方法と内容の違いについて!
└─リダイレクトとは?標準入力・出力、標準エラー出力等について!
(補足)シェルスクリプトの設計書とは?必要な項目や書き方等を解説!
Shellスクリプトを使いこなす上で欠かせない「演算子」。算術演算、比較演算、そして論理演算までを網羅した解説記事です。本記事では、それぞれの演算子の基本的な使い方から応用例、よくあるミスの回避方法まで詳しく紹介します。
初心者から中級者まで、スクリプト作成を効率化するための必読ガイドです!
算術演算子とは?
演算子っていきなり言われると分からない人もいると思いますので、簡単に説明します。
具体的には、足し算「+」や引き算「-」、掛け算「×(*)」、割り算「÷(/)」などの計算を行うときの記号ありますよね?これらの記号をコンピューターが使う時に演算子を使います。また、値や文字、モノ(オブジェクト)などを比較する場合にも、演算子を使用します。
算術演算子の基本的な使い方
算術演算って普段の生活をしているときに当たり前に暗算してしまっていると思うんですけど、コンピューターに計算させるためにはプログラムをちゃんと書いてあげないといけないんですね。なので、これからどんなシェルスクリプトを書けばいいのかを紹介していきます。
算術演算子 | 使用例 | 意味 |
+ | a + b | a に b を加える(加法) |
- | a - b | a から b を引く(減法) |
* | a * b | a に b をかける(乘法) |
/ | a / b | a を b で割る(除法) |
% | a % b | aの数値をbの数値で割った余りを返す(剰余法) |
# aの中身とbの中身を足した結果を表示します。
a=1
b=1
echo $((a + b))
1 2 3 4 | [root@CentOS7 ~]# a=1 [root@CentOS7 ~]# b=1 [root@CentOS7 ~]# echo $((a + b)) 2 |
# aの中身とbの中身を引いた結果を表示します。
a=1
b=1
echo $((a - b))
1 2 3 4 | [root@CentOS7 ~]# a=1 [root@CentOS7 ~]# b=1 [root@CentOS7 ~]# echo $((a - b)) 0 |
# aの中身とbの中身を掛けた数字を表示します。
a=1
b=1
echo $((a * b))
1 2 3 4 | [root@CentOS7 ~]# a=1 [root@CentOS7 ~]# b=1 [root@CentOS7 ~]# echo $((a * b)) 1 |
# aの中身とbの中身を割った数字を表示します。
a=1
b=1
echo $((a / b))
1 2 3 4 | [root@CentOS7 ~]# a=1 [root@CentOS7 ~]# b=1 [root@CentOS7 ~]# echo $((a / b)) 1 |
# aの数字をbの数字で割ったあまりを返えします。
a=1
b=1
echo $((a % b))
1 2 3 4 | [root@CentOS7 ~]# a=1 [root@CentOS7 ~]# b=1 [root@CentOS7 ~]# echo $((a % b)) 0 |
算術演算子の応用的な使い方
- 複雑な式の計算
$(( ))では、複数の演算子を組み合わせた複雑な計算も可能です。括弧を使用して計算の順序を制御します。
result=$(( (5 + 3) * 2 ))
echo $result # 出力: 16
- 変数を使用した計算
変数を使うことで、柔軟に値を操作できます。
a=10
b=4
result=$((a - b))
echo $result # 出力: 6
- 剰余演算(余りの計算)
剰余演算子 % を使うと、割り算の余りを求められます。
result=$((10 % 3))
echo $result # 出力: 1
この剰余算、ちょっと分かりずらいので補足します。主な使い道としては、表テーブル等の行の色を1段ごとに交互に変えたい場合などに、この剰余算を使用します。2で割ったあまりが0なら偶数、1なら奇数と言った具合です。ただ割るだけでなく、その余りを対象とします。
- 自動インクリメント・デクリメント
C言語と同様に、インクリメント(++)やデクリメント(--)も使用可能です。
a=5
((a++))
echo $a # 出力: 6
((a--))
echo $a # 出力: 5
- 少数を扱う方法
Shellスクリプトの算術演算は基本的に整数のみですが、小数計算を行う場合はbcコマンドを使用します。
result=$(echo "scale=2; 5 / 3" | bc)
echo $result # 出力: 1.66
算術演算子のよくあるエラーと対処法
- exprでエラーが出る場合
演算子の前後にスペースがないとエラーになります。
# NG例
result=$(expr 5+3)
# 正しい例
result=$(expr 5 + 3)
- 割り算で少数が表示されない
/演算子では整数計算しかできません。小数が必要な場合はbcを使います。
比較演算子とは?
先程は算術演算の紹介をしましたが、演算子というのは「算術演算子」だけでなく「比較演算子」という、演算子の左右にあるデータを比較をするための演算子もあるんです。
比較演算子はどういうときに使われているのかというと、入力された文字列が正しいかを確認したいときや、「if」文や「case」文といった制御構文を組み合わせて繰り返し処理をするときに使われています。
数値比較には-eqなどの演算子を使用しますが、文字列比較には=や!=を使用します。文字列比較における<や>は、[[ ]]で囲む必要があります。
「if」文や「case」文については、次回の記事で解説しています。
比較演算子の種類
Shellスクリプトにおける比較演算子は、条件を判定する際に非常に重要な役割を果たします。数値や文字列の比較だけでなく、条件分岐やループ処理でも使用されます。
数値比較演算子
下記の一覧は、数値を比較するために必要な演算子をまとめたものです。
比較演算子 | 使用例 | 意味 |
-eq | a -eq b | aとbが等しければ真 |
-ge | a -ge b | aがbより大きい、もしくは等しければ真 |
-gt | a -gt b | aがbより大きければ真 |
-le | a -le b | aがbより小さい、もしくは等しければ真 |
-lt | a -lt b | aがb未満であれば真 |
-ne | a -ne b | aとbが等しくなければ真 |
この比較演算子は、シェルスクリプトを作成する上で、欠かすことは出来ないモノです。比較演算子を使わないシェルスクリプトはまず無いといってよいでしょう。
下記に、最もよく使うであろう「リターンコード」の比較判定文を試してみます。なんだったらこの構文を丸ごと暗記しても良いくらいよく使います。
echo "Hello World"
if [ $? -eq 0 ]; then
echo "コマンドは、正常に実行しました。"
fi
1 2 3 4 5 6 | [root@CentOS7 ~]# echo "Hello World" Hello World [root@CentOS7 ~]# if [ $? -eq 0 ]; then > echo "コマンドは、正常に実行しました。" > fi コマンドは、正常に実行しました。 |
「echo」コマンドで正常に文字列”Hello World”の出力が終えたため、終了ステータスコードは「真(true)」を取得しています。
文字列比較演算子
シェルスクリプトで文字列を比較する為に必要なプログラムは、たった1行書くだけで十分です。しかし、if-else文のスクリプトを作成する場合は多少プログラムを記述する必要があります。
下記の一覧は、文字列を比較するために必要な演算子をまとめたものです。
比較演算子 | 使用例 | 意味 |
-n | -n 文字列 | 文字列の長さが0より大きければ真 |
-z | -z 文字列 | 文字列の長さが0であれば真 |
= | 文字列A = 文字列B | 文字列Aと文字列Bが等しければ真 |
!= | 文字列A != 文字列B | 文字列Aと文字列Bが等しくなければ真 |
ココに注意
シェルスクリプトの比較式には「比較演算子」の左右に空白(半角スペース)が必要です(代入とは別)。また、比較する変数を「ダブルクォーテーション」で囲まないと、変数が空のときに構文エラーとなってしましますので注意してください。
具体的に、演算子をどのように使っているのかを紹介してみましょう。今回は「ワンライナー」でシェルを記述してみます。
ワンライナー?
ワンライナーとは、スクリプト構文を、インデントや改行など一切行わず、1行にすべて詰め込む記述法を指します。ベテランエンジニアが良く用いる記述法です。
条件文の書式
[ 条件文 ] && コマンド1 || コマンド2
a="文字列1"
b="文字列2"
echo `[ "$a" = "$b" ] && echo "同じ文字列ですね" || echo "違う文字列ですね"`
1 2 3 4 | [root@CentOS7 ~]# a="文字列1" [root@CentOS7 ~]# b="文字列2" [root@CentOS7 ~]# echo `[ "$a" = "$b" ] && echo "同じ文字列ですね" || echo "違う文字列ですね"` 違う文字列ですね |
上記では、それとなく三項演算子チックに記述していますが、シェルには三項演算子は存在しません。ただし、上記の様にそれらしく振舞うことは可能です。
比較演算子の基本的な使い方
- 数値の比較
数値を比較して条件分岐を行う場合の例です。
a=5
b=10
if [ $a -lt $b ]; then
echo "aはbより小さい"
else
echo "aはb以上"
fi
- 文字列の比較
文字列の一致や不一致を判定する例です。
str1="hello"
str2="world"
if [ "$str1" = "$str2" ]; then
echo "文字列は一致しています"
else
echo "文字列は一致していません"
fi
- 辞書順での比較
文字列を辞書順で比較する場合は、[[ ]]を使用します。
str1="apple"
str2="banana"
if [[ "$str1" < "$str2" ]]; then
echo "$str1 は $str2 より辞書順で小さい"
else
echo "$str1 は $str2 より辞書順で大きい"
fi
比較演算子の応用的な使い方
- 複数条件を組み合わせる
論理演算子&&(AND)や||(OR)を使って複数条件を組み合わせることができます。
a=15
if [ $a -gt 10 ] && [ $a -lt 20 ]; then
echo "aは10より大きく、20未満です"
fi
- ファイル名の比較
ファイル名や入力値を条件として比較することも可能です。
read -p "ファイル名を入力してください: " filename
if [ "$filename" = "test.txt" ]; then
echo "指定されたファイルはtest.txtです"
else
echo "指定されたファイルは異なります"
fi
比較演算子のよくあるエラーと対処法
- スペースが不足している
演算子の前後にはスペースが必要です。
# NG例
if [ $a-gt$b ]; then
# 正しい例
if [ $a -gt $b ]; then
- 変数が空の場合のエラー
比較対象の変数が空だとエラーになります。
以下のように変数が空でないことを確認する方法を使いましょう。
if [ -n "$var" ] && [ $var -eq 5 ]; then
echo "varは5です"
fi
比較演算子を使いこなすことで、Shellスクリプトでの条件分岐やループ処理をより効率的に行えます。数値と文字列で使用する演算子が異なる点や、スペースの有無など注意点を押さえ、実践で活用してみてください!
論理演算子とは?
Shellスクリプトでは、条件を組み合わせて複雑なロジックを記述する際に論理演算子を使用します。特に条件分岐やループ処理において役立つツールです。
論理演算子の種類
Shellスクリプトで使用される主な論理演算子は以下の通りです。
演算子 | 意味 |
&& | 直前に実行されたコマンドの結果が真(終了ステータスが「0」)である場合のみ、次のコマンドを実行する。 |
| | | 直前に実行されたコマンドの結果が偽(終了ステータスが「0」以外)である場合のみ、次のコマンドを実行する。 |
! | 条件の真偽を逆転させます。 |
論理演算子の基本的な使い方
- AND(&&)を使った条件の組み合わせ
複数の条件がすべて真である場合に処理を実行します。
a=10
b=20
if [ $a -gt 5 ] && [ $b -lt 30 ]; then
echo "aは5より大きく、bは30未満です"
fi
- OR(||)を使った条件の組み合わせ
いずれかの条件が真であれば処理を実行します。
a=10
b=40
if [ $a -gt 20 ] || [ $b -lt 50 ]; then
echo "aが20より大きい、またはbが50未満です"
fi
- NOT(!)で条件を否定する
条件を否定して、真を偽に、偽を真に変えます。
a=5
if ! [ $a -eq 10 ]; then
echo "aは10ではありません"
fi
論理演算子の応用的な使い方
- ファイルの存在確認とアクセス権チェック
論理演算子を使って、複数の条件を組み合わせたファイル確認スクリプトを作成します。
filename="example.txt"
if [ -e $filename ] && [ -r $filename ]; then
echo "ファイルは存在し、読み取り可能です"
else
echo "ファイルが存在しないか、読み取り不可です"
fi
- ユーザー入力の検証
ユーザーが入力した値が条件を満たすか確認するスクリプトです。
read -p "値を入力してください: " input
if [ $input -ge 10 ] && [ $input -le 20 ]; then
echo "入力値は10以上20以下です"
else
echo "入力値は範囲外です"
fi
- 複数条件のチェックでスクリプトの効率化
論理演算子を使えば、複数の条件を1行で記述でき、スクリプトを簡潔に保つことができます。
username="admin"
password="password123"
if [ "$username" = "admin" ] && [ "$password" = "password123" ]; then
echo "ログイン成功"
else
echo "ログイン失敗"
fi
論理演算子のよくあるエラーと対処法
- スペースの重要性
論理演算子や条件の前後にはスペースが必要です。以下のような記述はエラーになります。
if [ $a -gt 5]&&[ $b -lt 10 ]; then # NG
if [ $a -gt 5 ] && [ $b -lt 10 ]; then # OK
- [と[[の違い
[はPOSIX準拠で、単純な条件式に使用します。
[[はBash特有で、より複雑な条件式をサポートします。特に文字列の比較では[[を推奨します。
論理演算子を使用することで、Shellスクリプト内での条件判定を効率的かつ柔軟に記述できます。基本的な演算子を正しく使い、応用例を参考にして、複雑な条件式を作成してみてください!論理演算子をマスターすることで、スクリプトの質を大幅に向上させることができます。
ファイル演算子とは?
Shellスクリプトでは、ファイルの存在確認や種類、アクセス権の確認などを行うためにファイル演算子を使用します。これにより、スクリプトの柔軟性と実用性が大幅に向上します。
ファイル演算子の種類
下記の一覧は、ファイルやディレクトリを比較するために必要な演算子をまとめたものです。
比較演算子 | 使用例 | 意味 |
-d | -d ディレクトリ | ディレクトリであれば真 |
-e | -e ファイル | ファイルが存在すれば真 |
-f | -f ファイル | 通常のファイルであれば真 |
-L | -L シンボリックリンク | シンボリックリンクであれば真 |
-r | -r ファイル | 読み取り可能ファイルなら真 |
-w | -w ファイル | 書き込み可能ファイルなら真 |
-x | -x ファイル | 実行可能ファイルなら真 |
-s | -s ファイル | サイズが0以上のファイルなら真 |
ファイル演算子の基本的な使い方
- ファイルの存在確認
ファイルが存在するかを確認します。
file="example.txt"
if [ -e $file ]; then
echo "ファイルは存在します"
else
echo "ファイルは存在しません"
fi
- ディレクトリの存在確認
ディレクトリが存在するかを確認します。
dir="my_directory"
if [ -d $dir ]; then
echo "ディレクトリは存在します"
else
echo "ディレクトリは存在しません"
fi
- アクセス権の確認
ファイルが読み取り可能か、書き込み可能か、実行可能かを確認します。
file="example.sh"
if [ -r $file ] && [ -x $file ]; then
echo "ファイルは読み取り可能で実行可能です"
else
echo "ファイルは読み取り不可または実行不可です"
fi
ファイル演算子の応用的な使い方
- 空のファイルかどうかを判定
-s 演算子を使ってファイルが空でないことを確認します。
file="data.txt"
if [ -s $file ]; then
echo "ファイルは空ではありません"
else
echo "ファイルは空です"
fi
- 条件を否定する
否定演算子 ! を使って条件を反転させます。
file="test.txt"
if [ ! -e $file ]; then
echo "ファイルは存在しません"
else
echo "ファイルは存在します"
fi
- スクリプト内でファイル操作を制御
ファイル演算子を使ってファイル操作を安全に行います。
例: ファイルが存在しない場合に作成するスクリプト
file="new_file.txt"
if [ ! -e $file ]; then
echo "新しいファイルを作成します"
touch $file
else
echo "ファイルは既に存在します"
fi
ファイル演算子のよくあるエラーと対処法
- ファイル名にスペースが含まれる場合
ファイル名にスペースが含まれている場合は、ダブルクォートで囲む必要があります。
file="my file.txt"
if [ -e "$file" ]; then
echo "ファイルは存在します"
fi
- 変数の未定義エラー
変数が未定義の場合にエラーになることを防ぐため、変数をダブルクォートで囲む習慣をつけましょう。
ファイル演算子を活用することで、ファイルやディレクトリの存在確認、アクセス権のチェックなどが容易になります。これにより、スクリプトの実用性が大幅に向上します。基本的な使い方を押さえた上で、応用例を参考にスクリプトの改善に挑戦してみてください!
演算子の実践とよくある疑問への回答
Shellスクリプトで演算子を活用するための実用的なスクリプト例と、よく寄せられる疑問をまとめました。初心者がつまずきやすいポイントや応用テクニックを一挙に解説します。
演算子を使った実用スクリプト例
Shellスクリプトでは、演算子を活用することで効率的かつ柔軟なスクリプトを作成できます。このセクションでは、算術演算子、比較演算子、論理演算子、ファイル演算子を使った実用的なスクリプト例をいくつか紹介します。
- ディスク使用率を監視するスクリプト
ディスク使用率が一定の閾値を超えた場合に警告を出すスクリプトです。
#!/bin/bash
threshold=80 # 使用率の閾値
disk_usage=$(df / | grep / | awk '{print $5}' | sed 's/%//')
if [ $disk_usage -ge $threshold ]; then
echo "警告: ディスク使用率が${threshold}%を超えています!(現在: ${disk_usage}%)"
else
echo "ディスク使用率は正常です。(現在: ${disk_usage}%)"
fi
- ファイル更新日時をチェックするスクリプト
指定したファイルが一定期間内に更新されていない場合に通知を出します。
#!/bin/bash
file="example.txt"
threshold_days=7 # 更新が行われていない日数の閾値
if [ -e $file ]; then
last_modified=$(stat -c %Y $file)
current_time=$(date +%s)
age=$(( (current_time - last_modified) / 86400 ))
if [ $age -gt $threshold_days ]; then
echo "警告: ファイル $file は ${threshold_days}日以上更新されていません!"
else
echo "ファイル $file は正常に更新されています。"
fi
else
echo "エラー: ファイル $file が存在しません。"
fi
- 複数の条件をチェックするログインスクリプト
ユーザー名とパスワードをチェックし、条件を満たす場合のみログイン成功とします。
#!/bin/bash
correct_username="admin"
correct_password="password123"
read -p "ユーザー名を入力してください: " username
read -sp "パスワードを入力してください: " password
echo ""
if [ "$username" = "$correct_username" ] && [ "$password" = "$correct_password" ]; then
echo "ログイン成功!"
else
echo "ログイン失敗。ユーザー名またはパスワードが間違っています。"
fi
- ファイルサイズをチェックして削除するスクリプト
指定したファイルが一定サイズを超えた場合に削除するスクリプトです。
#!/bin/bash
file="large_file.txt"
max_size=1024 # 最大サイズ(KB単位)
if [ -e $file ]; then
file_size=$(du -k $file | awk '{print $1}')
if [ $file_size -gt $max_size ]; then
echo "警告: ファイルサイズが${max_size}KBを超えています。削除します。"
rm $file
else
echo "ファイルサイズは正常です。(現在: ${file_size}KB)"
fi
else
echo "ファイル $file が存在しません。"
fi
- ユーザーの年齢を判定するスクリプト
入力された年齢に基づいてメッセージを表示します。
#!/bin/bash
read -p "あなたの年齢を入力してください: " age
if [ $age -lt 18 ]; then
echo "未成年です。"
elif [ $age -ge 18 ] && [ $age -lt 65 ]; then
echo "成人です。"
else
echo "高齢者です。"
fi
これらのスクリプト例を参考にして、実際のニーズに応じたShellスクリプトを作成してみてください。演算子を活用することで、効率的で高度な処理が可能になります。
演算子のよくある質問への回答
Shellスクリプトを学習する中で、初心者や中級者がよく直面する疑問をQ&A形式でまとめました。
Shellスクリプトで算術演算子を使う場合、小数点を扱えますか?
Shell標準では非対応ですが、bcやawkを使えば可能です。
result=$(echo "scale=2; 5 / 3" | bc)
echo $result # 出力: 1.66
比較演算子で文字列の比較を行う際、エラーになる原因は何ですか?
文字列比較でエラーが発生する主な原因は以下の通りです。
- スペースが不足している
演算子の前後にスペースが必要です。
# 誤った例
if [ "$str1"="abc" ]; then
# 正しい例
if [ "$str1" = "abc" ]; then
- 未定義の変数を使用している
変数が未定義だとエラーになる場合があります。
必ず変数をダブルクォートで囲む習慣をつけましょう。
if [ "$str1" = "abc" ]; then
複数の条件を組み合わせる際にどのような注意点がありますか?
複数の条件を組み合わせる際には以下の点に注意してください。
- 括弧の使い方: 条件のグループ化には[や[[を正しく使います。
- スペースの確保: 論理演算子(&&や||)の前後にスペースが必要です。
if [ $a -gt 5 ] && [ $b -lt 10 ] || [ $c -eq 15 ]; then
echo "条件を満たしました"
fi
ファイル演算子を使って特定のファイルが存在しない場合に処理をスキップできますか?
ファイル演算子-eを使用して、ファイルの存在を確認し、存在しない場合に処理をスキップできます。
file="test.txt"
if [ ! -e $file ]; then
echo "ファイルが存在しないため、処理をスキップします"
else
echo "ファイルが存在します"
fi
Shellスクリプト内でエラーが発生した際にデバッグする方法は?
Shellスクリプトのデバッグには以下の方法があります。
ポイント
- set -xでデバッグを有効化
set -xを使用すると、スクリプト実行中に実行される各コマンドがターミナルに出力されます。 - set+xでデバッグを無効化
set +xは、デバッグ出力を無効化するために使用します。スクリプト全体をデバッグ出力する必要がない場合、必要な箇所だけset -xを使い、その後にset +xで通常の出力に戻すことができます。
set -x
# デバッグ対象のスクリプト
set +x
- echoで値を確認: 変数の値や条件式の結果を確認します。
echo "変数aの値は: $a"
Shellスクリプトで現在日時を使ったファイル名を生成する方法は?
dateコマンドを使用して現在日時を取得し、それをファイル名に組み込むことができます。
timestamp=$(date "+%Y%m%d%H%M%S")
filename="backup_$timestamp.tar.gz"
echo "作成されたファイル名: $filename"
条件分岐が複雑になる場合、どうやって簡潔に記述できますか?
複雑な条件分岐を簡潔にするには、以下の方法を検討してください
ポイント
- case文を使用
特定の値に応じた処理を分岐させるのに適しています。 - 関数化
繰り返し使用する処理を関数として定義することでスクリプトを整理できます。
case $input in
"start")
echo "開始します"
;;
"stop")
echo "停止します"
;;
*)
echo "無効な入力です"
;;
esac
Shellスクリプトの変数を他のスクリプトで共有する方法は?
exportコマンドを使うことで変数を環境変数として他のスクリプトで共有できます。
export VAR="共有変数"
./other_script.sh
これらのFAQを参考に、Shellスクリプトの基本から応用までの理解を深めてください。疑問が解決しない場合は、manコマンドやオンラインリソースを活用することでさらに詳しい情報を得ることができます!
ファイルやディレクトリの比較例については、下記のリンクページを参照ください。