条件式 や算術演算子を使う
if 文の条件を書く場合 [ ] (testコマンド)よりも (条件式)を使うべき。
testコマンドの場合、条件式を表す<>, (), &&, ||をエスケープする必要があったが、条件式の場合はそのまま書ける。
AND条件やOR条件を表す-aや-oの演算子がそれぞれ&&, || で書くことができ
# test [ $i -lt 10 -a $i -lt 15 ] && ls # 条件式 [[ $i -lt 10 && $i -lt 15 ]] && ls # 算術演算式 (( i <10 && i < 15 )) && ls
条件の各数式に括弧をつける場合を見るとより、エスケープの必要性の違いが分かる。
# test [ \( $i -lt 10 \) -a \( $i -lt 15 \) ] && ls # 条件式 [[ ($i -lt 10) && ($i -lt 15) ]] && ls # 算術演算式 (( (i<10) && (i<15) )) && ls
ifを使わないで&&や||を代用する
&&で接続された場合、前方が真であれば後方が実行される。後方をグループコマンドで書くと、if文を使わなくても書ける。
cmp -s file1 file2 && { echo '重複を削除します' rm -f file2 }
`||`で接続された場合、前方が偽であれば後方が実行される。後方をグループコマンドで書くと、if文を使わなくても書ける。
test -f file1 || { echo 'file1が存在しません' exit 1 } # 条件式 [[ -f README.md ]] && cat README.md
elseを含むif文の構造
testコマンドが真ならば&&以降が評価され, 偽なら `||`が評価される。
[ $i -lt 10 ] && { # "$i"でもok echo 'iの値は10未満です' } || { echo 'iの値は10以上です' } # 条件式で書くと [[ $i -lt 10 ]] && echo "10未満" # 算術式で書くと ((i < 10)) && echo "10未満"
whileでwhileの横にtestコマンドを使わない
sumの初期値は0なのに最初にsum<100という明らかに真の評価を行ってしまっている。
i=0 sum=0 while [ "$sum" -lt 100 ] do i=`expr "$i" + 1` sum=`expr "$sum" + "$i"` done
whileの最後にtestコマンドを書けば最初の評価を行わずに1回目のループに行くことができる。
i=0 sum=0 while i=`expr "$i" + 1` sum=`expr "$sum" + "$i"` [ "$sum" -lt 100] do :; done
パラメタ展開を使いこなす
Shellの文字列変換操作は意外と優秀
# varが未定義 or 空文字ならばdefaultに展開される # : は空文字 # - は未定義 ${var:-default} # varが未定義ならばdefaultに展開される ${var-default} # varが空文字列ならばdefaultに展開される ${var:default} # varが未定義 or 空文字ならばdefaultがvarに代入される ${var:=default} # varが未定義 or 空文字列の場合にerrorを出力して終了する ${var:?error} # varが定義されていればvalueの値に展開される ${var:+value} # varの文字列長に展開される ${#var} # 部分文字列 ${var:offset:length} # varの左側から最初に一致したpattern1がpattern2に置き換えられる ${var/pattern1/pattern2} # varの左側からすべてのpattern1がpattern2に置き換えられる ${var//pattern1/pattern2}