シェルスクリプトの作成と実行方法
シェルスクリプトは、LinuxやUnix系OSでコマンドを自動化するために使用されるテキストファイルです。まず、script.shという名前のファイルを作成し、エディタ(例: vim)で編集します。スクリプトの先頭にはインタプリタのパスを指定します。
#!/bin/bash
# または
#!/bin/sh
# /bin/shは多くのシステムでdashを指している
スクリプトに実行権限を与えるには、以下のコマンドを使用します。
chmod u+x script.sh
実行方法は主に3つあります。
- ./script.sh:カレントディレクトリ内のスクリプトを実行します。実行権限が必要です。
- sh script.sh:明示的にshインタプリタを呼び出して実行します。権限がなくても実行可能です。
- source script.sh または . script.sh:現在のシェル環境内でスクリプトを読み込み、変数や関数の変更が継続します。
変数の扱い方
変数は代入時にスペースを入れず、参照時は$記号を使います。
username="takaba"
count=100
greeting="Hello, World!"
変数の展開は、ダブルクォート内では有効ですが、シングルクォート内では無視されます。
echo "こんにちは、$username" # 出力: こんにちは、takaba
echo 'こんにちは、$username' # 出力: こんにちは、$username
文字列の長さを取得したり、部分文字列を抽出することもできます。
text="shell scripting"
echo ${#text} # 長さ: 15
echo ${text:0:5} # 先頭5文字: shell
不要になった変数はunsetで削除できます。
unset username
環境変数の永続化
カスタムスクリプトをどこからでも実行可能にするには、そのパスをPATH環境変数に追加します。
export PATH="/home/user/scripts:$PATH"
この設定はセッション終了後には消えてしまうため、永続化するには~/.bashrcや~/.profileに記述し、source ~/.bashrcで反映させます。
引数の受け渡し
スクリプトに引数を渡すことができます。各位置の引数は$1、$2のように参照します。
echo "スクリプト名: $0"
echo "第1引数: $1"
echo "全引数(結合): $*"
echo "全引数(個別): $@"
echo "引数の数: $#"
echo "直前のコマンドの終了コード: $?"
echo "プロセスID: $$"
算術演算
基本的な計算にはexprコマンドを使います。演算子の前後にスペースが必要です。
expr 5 + 3 # 加算
expr 10 - 4 # 減算
expr 6 \* 7 # 乗算(アスタリスクはエスケープ)
expr 20 / 4 # 除算
expr 10 % 3 # 剰余
複雑な式では括弧を使う場合、エスケープが必要です。
expr \( 2 + 3 \) \* 4 # 結果: 20
変数への代入にはコマンド置換を使います。
result=$(expr 8 \* 5)
echo $result # 出力: 40
ユーザーとの対話:readコマンド
readコマンドを使って、ユーザーの入力を取得できます。
read -p "名前を入力してください: " name
echo "こんにちは、$nameさん"
オプションで挙動を制御できます。
-t 10:10秒でタイムアウト-n 3:最大3文字まで入力
read -t 10 -n 3 -p "3文字以内で入力: " input
条件判定
数値比較には以下のような演算子を使います。
-eq:等しい-ne:等しくない-lt:より小さい-gt:より大きい
if [ "$a" -eq "$b" ]; then
echo "等しい"
fi
文字列の比較では=や!=を使います。
if [ "$str1" = "$str2" ]; then
echo "文字列は同じ"
fi
-zは空文字列かどうか、-nは非空かどうかを判定します。
論理演算と分岐
-a(AND)、-o(OR)で複数条件を組み合わせられます。
if [ "$age" -ge 18 -a "$has_license" = "yes" ]; then
echo "運転できます"
fi
if-elif-else構文で複数の条件分岐が可能です。
繰り返し処理
forループはリストや範囲に対して反復処理を行います。
for i in 1 2 3 4 5; do
echo "数値: $i"
done
seqコマンドやC言語風の二重括弧構文も利用できます。
for i in $(seq 1 5); do
echo $i
done
for ((j=1; j<=5; j++)); do
echo $j
done
whileループは条件が真の間、処理を繰り返します。
counter=1
while [ $counter -le 5 ]; do
echo $counter
counter=$((counter + 1))
done
untilループは条件が偽である限り、処理を続けます。
num=1
until [ $num -gt 5 ]; do
echo $num
num=$((num + 1))
done
case文による分岐
複数の値に基づいて処理を分岐させる場合に便利です。
read -p "数字を入力: " num
case $num in
1) echo "一" ;;
2) echo "二" ;;
*) echo "その他" ;;
esac
関数の定義と利用
繰り返し使う処理は関数として定義できます。
greet() {
local user=$1
echo "こんにちは、$userさん!"
}
greet "Yamada"
別のスクリプト内で定義された関数や変数を利用するにはsourceを使います。
# config.sh
username="admin"
role="system"
# main.sh
source ./config.sh
echo "ユーザー: $username, 権限: $role"
入出力のリダイレクト
標準出力をファイルに書き込むには>(上書き)または>>(追記)を使います。
ls > files.txt
date >> log.txt
標準入力をファイルから読み込むには<を使います。
sort < data.txt
ファイルディスクリプタ(0: 標準入力, 1: 標準出力, 2: エラー出力)を使って、出力先を分けることもできます。
command > output.log 2> error.log
出力を破棄したい場合は/dev/nullにリダイレクトします。
ls > /dev/null