Paepoi » ShellScript Tips » ShellScript Tips | 条件分岐
ShellScript Tips | 条件分岐
# 最終更新日 2019.12.01
更に bash, zsh では [[...]] も使える、この三つは下記のような場合はまったく同じです。
[[...]] はいったい何かというと [ の拡張と思えばいいようです。
上記で既に書いていますが単純な if 文であれば &&, || のほうが簡単かつ明解です。
[[ 条件式 ]] && 真の場合 || 偽の場合
ブレースでネストすることもできる。
ただし以下のような場合があるので注意。
上記のようにブレースはブロックスコープにならないので必ず or 演算もセットで使う。
何もしないならコロンを使うのが一番簡単。
elif を使う場合は素直に if を使ってください。
以下は条件式。
数値
文字列
ファイル
以上がありますがほとんど引数のことですね。
こんなふうに使います。
また条件を「|」記号で or 演算することもできる。
ただし C 言語の関数等と違い別プロセスとして実行されます。
親シェルの変数は参照できますが戻り値は $? を利用します。
関数の呼び出しに括弧は不要で引数は半角空白区切りで渡します。
関数側から引数を参照するには $1, $2... を利用、別プロセスなのでスクリプトの呼び出し引数とは違う。
等々、C 言語なんかを知っていると少し戸惑ってしまうと思います。
UNIX のコマンドが全部そうなっていることに気が付いたかな。
test コマンドと [[
test コマンドは真偽値を戻す、代わりに [...] を利用することもできる。更に bash, zsh では [[...]] も使える、この三つは下記のような場合はまったく同じです。
if test 1 -ne 2; then # ↓ if [ 1 -ne 2 ]; then # ↓ if [[ 1 -ne 2 ]]; then
[[...]] はいったい何かというと [ の拡張と思えばいいようです。
#!/bin/sh # = でパターンマッチ [[ おまえはアホ = *アホ ]] && echo 1 || echo 2 #=> 1 [[ おまえはスケベ = *アホ ]] && echo 1 || echo 2 #=> 2 # =~ で正規表現マッチ、単なる文字列探しにも使える [[ おまえはアホ =~ [(アホ|バカ)] ]] && echo 1 || echo 2 #=> 1 [[ おまえはスケベ =~ [(アホ|バカ)] ]] && echo 1 || echo 2 #=> 2 # 辞書順で文字列比較、数値優先には当然ならないけど [[ test2.txt < test12.text ]] && echo 1 || echo 2 #=> 2 # 論理演算子が &&, || になる [[ a = a && b = b ]] && echo 1 #=> 1
if
if については説明不要かと。上記で既に書いていますが単純な if 文であれば &&, || のほうが簡単かつ明解です。
[[ 条件式 ]] && 真の場合 || 偽の場合
if [[ $PWD = $HOME ]]; then
echo ホームです
else
cd ~
fi
# ↓
[[ $PWD = $HOME ]] && echo ホームです || cd ~
ブレースでネストすることもできる。
ただし以下のような場合があるので注意。
#!/bin/sh
motor=スズキのバイクはかっこいい
[[ $motor =~ スズキ ]] && {
[[ $motor =~ かっこいい ]] && echo ヨシ!
[[ $motor =~ かっこわるい ]] && echo シネ!
} || {
echo ダセーwwwww
}
ダセーwwwwwも表示されてしまうはずです。上記のようにブレースはブロックスコープにならないので必ず or 演算もセットで使う。
何もしないならコロンを使うのが一番簡単。
[[ $motor =~ かっこわるい ]] && echo シネ! || :
elif を使う場合は素直に if を使ってください。
以下は条件式。
数値
| 条件式 | 意味 |
|---|---|
| 数値 -eq 数値 | == |
| 数値 -ne 数値 | != |
| 数値 -ge 数値 | >= |
| 数値 -gt 数値 | > |
| 数値 -le 数値 | <= |
| 数値 -lt 数値 | < |
| 条件式 | 意味 |
|---|---|
| -n 文字列 | 文字列が一文字以上ある |
| -z 文字列 | 文字列がゼロ文字 |
| 文字列1 = 文字列2 | 等しい |
| 文字列1 != 文字列2 | 等しくない |
| 条件式 | 意味 |
|---|---|
| -G ファイル名 | ファイルのグループが実行ユーザー |
| -O ファイル名 | ファイルの所有者が実行ユーザー |
| -S ファイル名 | ソケット |
| -b ファイル名 | ブロックデバイスファイル |
| -c ファイル名 | キャラクタデバイスファイル |
| -d ファイル名 | ディレクトリ |
| -e ファイル名 | 存在確認 |
| -f ファイル名 | 通常ファイル |
| -g ファイル名 | SGID がある |
| -h ファイル名, -L ファイル名 | シンボリックリンク |
| -k ファイル名 | スティッキービットがある |
| -p ファイル名 | 名前付きパイプ |
| -r ファイル名 | 読み取り可能 |
| -s ファイル名 | ファイルサイズがゼロではない |
| -t ファイル名 | 端末でオープンされてい |
| -u ファイル名 | SUID がある |
| -w ファイル名 | 書き込み可能 |
| -x ファイル名 | 実行可能 |
| ファイル名1 -nt ファイル名2 | ファイル名1のほうが修正時刻が新しい |
| ファイル名1 -ot ファイル名2 | ファイル名1のほうが修正時刻が古い |
| ファイル名1 -ef ファイル名2 | デバイス番号と i ノード番号が同じ |
特殊変数
| 特殊変数 | 解説 |
|---|---|
| $n (数字) | $0 はスクリプト名、以降 $1, $2…${10}, ${11}… と引数が並ぶ |
| $# | 引数の個数 |
| $@ | $0 以外の全ての引数("$@" の場合 "$1" "$2" …") |
| $* | $0 以外の全ての引数("$*" の場合 "$1 $2 …") |
| $? | 最後に実行したコマンドの終了ステータス |
| $! | 最後に実行したバックグラウンドコマンドの PID |
| $$ | シェルの PID |
| $- | 現在のオプションフラグ |
以上がありますがほとんど引数のことですね。
こんなふうに使います。
#!/bin/sh
echo ディレクトリ名で圧縮します
if [[ $# -eq 0 ]]; then
echo 引数が無いよ
else
path=`pwd`
name=${path##*/}
file-roller --add-to="${name}.tar.gz" "$@"
fi
case
case 文は文字列が条件に一致するかで分岐する。| 条件 | 意味 |
|---|---|
| ? | 一文字 |
| * | ワイルドカード |
| [...] | [...] に含まれる一文字 |
| [!...] | [!...] に含まれない一文字 |
#!/bin/sh
case $USER in
root|syacho) echo おはようございます ;;
sasakima-nao) echo おまえかよ ;;
bite-*) echo うぃーす ;;
*) echo 誰だヨ! ;;
esac
関数
シェルスクリプトも関数が作れます。ただし C 言語の関数等と違い別プロセスとして実行されます。
親シェルの変数は参照できますが戻り値は $? を利用します。
関数の呼び出しに括弧は不要で引数は半角空白区切りで渡します。
関数側から引数を参照するには $1, $2... を利用、別プロセスなのでスクリプトの呼び出し引数とは違う。
等々、C 言語なんかを知っていると少し戸惑ってしまうと思います。
#!/bin/sh
your_motor_cycle() {
if [[ $1 = スズキ ]]; then
owner_var=かっこいい # 親の変数を参照できる
return 0
fi
return 1
}
owner_var=ダサい!
# 関数呼び出し、引数は ISF 区切りで渡す
your_motor_cycle スズキ
# if test func みたいにできない
[[ $? ]] && echo $owner_var || echo 失敗
どうしても戻り値が欲しいならパイプを使う。UNIX のコマンドが全部そうなっていることに気が付いたかな。
#!/bin/sh
suzuki() {
echo $1カッコイイ
return 0
}
suzuki スズキのバイクは | cat -n
# 変数に入れたい場合
car=`suzuki 車も`
echo スズキは$car
Copyright(C) sasakima-nao All rights reserved 2002 --- 2025.