UNIX/Linuxの部屋 用語集:シェルスクリプト

TOP UNIX/Linuxの部屋 UNIX/Linuxコマンド一覧 用語集 新版 由来/読み方辞書 環境変数マニュアル Cシェル変数 システム設定ファイル システムコール・ライブラリ ネットワークプログラミングの基礎知識 クラウドサービス徹底比較・徹底解説




用語集 シェルスクリプト コマンド実行を自動実行するためのファイル (if/else/foreach/while/case/switch) このエントリーをはてなブックマークに追加

最終更新


シェルスクリプトは
#!/bin/sh
echo "Hello World"
などと、シェルが解釈できるコマンドを羅列したファイルのことを指す。


sh が解釈できるシェルスクリプトのことを「sh スクリプト」(シェルスクリプトまたはエスエイチスクリプト)、csh が解釈できるシェルスクリプトのことを「csh スクリプト」(シーシェルスクリプト) と呼ぶことがある。

シェルスクリプトの作り方
vi や emacs 等のエディタで
#!/bin/sh
echo "Hello World"
というファイルを sample.sh などのファイル名で保存する。その後、
% chmod +x sample.sh
として実行権限を付与することで、
% ./sample.sh
Hello World
と実行できる。

sh・bash でのシェル変数セット
単純に文字列を代入し、表示する。
hoge=FUGA
echo $hoge
"=" の前後に空白を入れて下記のようにするとうまく動かない。引数 "=" と "FUGA" を渡して "hoge" コマンドを実行する、と解釈されるためである。
hoge = FUGA
改行コード入りの文字列を代入し、表示する。変数を利用する際、"" で囲むことで改行が維持される ("" で囲まないと IFS により 1行になってしまう)。
hoge="abc
def"
echo "$hoge"

sh・bash での変数置換
${var} 変数の値をそのまま返す。
${var:-word} 変数が未定義か空文字の場合、word を返す ($var に保存しない)
${var:=word} 変数が未定義か空文字の場合、word を返す ($bar にも保存する)
${var:?word} 変数が未定義か空文字の場合、標準エラー出力に word を出力し、スクリプトを終了する。
${var:+word} 変数がセットされている場合、word を返す。

sh・bash での環境変数セット
HOGE=FUGA
export HOGE
export HOGE=FUGA # 代入と export を同時に行ってもよい

sh・bash での一定回数のループ
i=0
while [ $i -lt 5 ]; do
echo $i
i=`expr $i + 1`
done
seq コマンドを使ってもよい。
for i in `seq 1 10`; do
echo "No: $i"
done
これは bash のみだと思うが、下記のようにも書ける。
for i in {1..10}; do
echo "No: $i"
done
これも bash のみだと思うが、for (( expr1 ; expr2 ; expr3 )) という書き方もできる。
for (( i=0 ; i<10 ; i++ )); do
echo "No: $i"
done

sh・bash でのリスト処理
vars="x y z"
for var in $vars; do
echo $var
done

sh・bash での行単位の処理
コマンド実行結果から:
ls -l | while read line; do
echo $line
done
ファイルから:
while read line; do
echo $line
done < file.txt
ヒアドキュメントで:
while read line; do
echo $line
done <<END
hoge
fuga
END

bash での配列初期化 【2018-12-28追加】
myarray=()
→ 空配列
myarray=(a0 a1 a2)
→ インデックス0番目に a0、1番目に a1、2番目に a2 を設定
myarray=([0]=a0 [1]=a1 [3]=a3)
→ インデックスを明示的に指定。

bash での配列要素参照 【2018-12-28追加】
myarray=(a0 a1 a2)
echo ${myarray[0]}
→ 結果は a0
echo ${myarray[1]}
→ 結果は a1
echo $myarray
→ 結果は a0

bash での配列要素数を参照 【2018-12-28追加】
myarray=(a0 a1 a2)
echo ${#myarray[@]}
→ 結果は 3

bash での要素の値を更新・追加・削除 【2018-12-28追加】
更新は普通に代入すればよい。
myarray[1]=a1xx
unset で要素を削除できる。
unset myarray[1]
末尾に追加:
myarray=(xxx yyy "${myarray[@]}")
myarray+=(xxx yyy)
先頭に追加:
myarray=("${myarray[@]}" xxx yyy)

bash での配列をすべて表示 【2018-12-28追加】
要素のみでよいなら下記のようにする。
myarray=(a0 a1 a2)
echo ${myarray[@]}
→ 結果は a0 a1 a2
ループで全要素を取得する例。
for i in "${myarray[@]}"; do
echo "$i"
done

インデックスから全要素を取得する例。
myarray=([0]=a0 [1]=a1 [3]=a3)
echo ${!myarray[@]}
ループでまわす場合は下記。
for i in "${!myarray[@]}"; do
echo "$i": "${myarray[$i]}"
done

sh・bash でのファイル名の取得
ファイルグロブを使って:
for file in *.txt; do
echo $file
done
コマンドの実行結果を使って:
for file in `ls | grep -v abc`; do
echo $file
done
for file in `find . -name \*.txt`; do
echo $file
done

sh・bash での if 文
if [ $var = "abc" ]; then
echo "var is abc"
elif [ $var = "def" ]; then
echo "var is def"
else
echo "var is not abc nor def"
fi
「=」以外にも、「!=」「>」「<」や、「-f」「-d」などのファイルテスト演算子を使うことができるが、test コマンドを参照してほしい。

sh・bash での continue・break
continue・break は for・while から脱出・次ループへ移動を行う。
cotinue 数字
break 数字
などとすることで、内側から何個目の for・while に対しての指示なのかを指定できる。
continue
continue 1

break
break 1
は、それぞれ等価である。
for file in `ls`; do
if [ $file = "hoge.txt" ]; then continue
if [ $file = "fuga.txt" ]; then break
done

sh・bash での switch 文
case $var in
hoge)
echo "var is hoge"
;;
foo|bar)
echo "var is foo or bar"
;;
*)
echo "var is unknown"
;;
esac

sh・bash での関数
sh・bash では、下記のようにして関数を作成することができる。
myfunc () {
echo "myfunc の処理"
}
bash ならば関数定義の先頭に function をつけてもよい (function をつけてもつけなくても挙動は同じ)。
function myfunc () {
...
}
定義した関数を実行するには、下記のように単に関数名を書けばよい (呼び出し時にカッコなどは不要)。
myfunc

引数を処理する場合、コマンドパラメータ取得時のように $#・$1・$2 などの変数を使うことができる。
myfunc_arg () {
echo "引数の個数: $#"
echo "引数1 $1"
echo "引数2 $2"
}
myfunc_arg abc def
上記の実行結果は下記のようになる。
% ./sample.sh
引数の個数: 2
引数1 abc
引数2 def

sh・bash の関数内のローカル変数
bash と一部の sh では、local コマンドを使うことで、ローカル変数の定義・宣言ができる。
myfunc () {
local var="1"
}
詳細は local コマンドのページを参照のこと。

sh・bash で、コマンドを実行し、終了ステータスを取得する 【2018-03-06 追加】
コマンドを実行したい場合、コマンド名を記述すればよい。その後 $? が 0 であれば正常終了、
0 以外であれば異常終了である。
command
ret=$?
if [ $ret != 0 ]; then
command がエラー
else
command が正常終了
fi

$? は、直前のコマンドの結果で上書きされるので、
command
echo $?
if [ $? != 0 ]; then 〜
はうまく動かない。echo の結果 (ほとんどの場合 0) で上書きされるからである。ちなみに変数代入も $? を上書きするので、下記もうまくうごかない (if の判定は変数代入の結果をチェックしていることになる)。
command
ret=$?
if [ $? != 0 ]; then 〜

sh・bash で、Yes か No を答えさせる
while [ 1 ]; do
/bin/echo -n "Type Yes/No: "
read line
case $line in
[yY][eE][sS])
echo YES; break
;;
[nN][oO])
echo NO; break
;;
esac
done

bash であれば bash の内部コマンド select コマンドで入力を受け取ることも検討してみるとよい。

sh・bash での計算
$(( 〜 )) で囲むことで、計算を行う。内部では変数を $x ではなく x と書ける ($x と書いても動くようだが)。
x=10
y=20
z=$(( x + y * 3 ))
echo $z
→ 70 となる
bash の場合、代入する変数を declare -i にて数値型であることをあらかじめ宣言しておけば、カッコなどが不要になる。
declare -i z
x=10
y=20
z=x+y*3
echo $z

csh・tcsh におけるスクリプト
csh・tcsh での書き方を以下にまとめておく。

なお、世の中一般においては csh や tcsh でシェルスクリプトを書くことはよくないとされている。当ページ管理人としてはコマンドラインから使う分には tcsh が好きなので聞こえないふりをしてきた (そして Perl や Python でスクリプトを書いてきた)。

vi や emacs 等のエディタで
#!/bin/csh -f
echo "Hello World"
というファイルを sample.csh などのファイル名で保存する。その後、
% chmod +x sample.csh
として実行権限を付与することで、
% ./sample.csh
Hello World
と実行できる。


[[csh・tcsh での環境変数セット #csh-env-variable-set
setenv HOGE FUGA


csh・tcsh での一定回数のループ
set i=0
while ( $i < 5 )
echo $i
@ i = $i + 1
end

csh・tcsh でのリスト処理
set vars=(x y z)
foreach var ($vars)
echo $var
end


csh・tcsh での if 文
if ( $var = "abc" ) then
echo "var is abc"
else if ( $var = "def" ) then
echo "var is def"
else
echo "var is not abc nor def"
endif

csh・tcsh での continue・break
continue・break は foreach・while から脱出・次ループへ移動を行う。csh の continue・break は、最も内側のループにしか効かない。
foreach file (`ls`)
if ( $file = "hoge.txt" ) then
continue
endif
if ( $file = "fuga.txt" ) then
break
endif
end

csh・tcsh での switch 文
switch ($var)
case "hoge":
echo "var is hoge"
breaksw
case "foo":
case "bar":
echo "var is foo or bar"
breaksw
default:
echo "var is unknown"
breaksw
endsw

余談
シェルスクリプトのことを指して「シェル」と呼んではいけない。本人は略しているだけのつもりかもしれないが、端から見るとシェルとシェルスクリプトの区別が付いていないように見える。よくわかっていない人が
「ファイルが消えた原因はシェルのバグです」
と主張するとき、原因は sh や csh のバグではなく、ほとんどの場合その人が書いたシェルスクリプトのバグにすぎない。当ページ管理人のネット上・実社会での観測結果によると、「シェルスクリプト」を「シェル」と呼ぶ人のスキルは著しく低い傾向がある。