Heavy Watal

シェルスクリプト

if-then

# basic
if test -e ~; then
  echo 'test -e ~'
fi

# popular
if [ -e ~ ]; then
  echo '[ -e ~ ]'
fi

# bash/zsh extention; not POSIX
if [[ -e ~ ]]; then
  echo '[[ -e ~ ]]'
fi

# shortcut with exit status
test -e ~ && echo 'test -e ~ && echo' || echo 'not printed'
[ -e ~ ] && echo '[ -e ~ ] && echo' || echo 'not printed'
[[ -e ~ ]] && echo '[[ -e ~ ]] && echo' || echo 'not printed'
[[ ! -e ~ ]] && echo 'not printed' || echo '[[ ! -e ~ ]] || echo'

AND/OR

[ -e ~ -a -d ~ ] && echo '[-e ~ -a -d ~]'
[ -e ~ -o -f ~ ] && echo '[-e ~ -o -f ~]'
[ -e ~ ] && [ -d ~ ] && echo '[ -e ~ ] && [ -d ~ ]'
[[ -e ~ && -d ~ ]] && echo '[[ -e ~ && -d ~ ]]'
[[ -e ~ || -f ~ ]] && echo '[[ -e ~ || -f ~ ]]'

文字列

EMPTY=''
NOTEMPTY='content'
[ -z "$EMPTY" ] && echo '-z "$EMPTY"'
[ -n "$NOTEMPTY" ] && echo '-n "$NOTEMPTY"'
[ "$NOTEMPTY" != "$EMPTY" ] && echo '"$NOTEMPTY" != "$EMPTY"'
[ "$NOTEMPTY" = "content" ] && echo '"$NOTEMPTY" = "content"'
[[ "$NOTEMPTY" =~ "tent$" ]] && echo '"$NOTEMPTY" =~ "tent$"'

ファイル、ディレクトリ

[ -e ~ ] && echo '-e ~'
[ -d ~ ] && echo '-d ~'
[ -f ~/.bashrc ] && echo '-f ~/.bashrc'
[ -L ~/.bashrc ] && echo '-L ~/.bashrc'
[ -r ~/.bashrc ] && echo '-r ~/.bashrc'
[ -w ~/.bashrc ] && echo '-w ~/.bashrc'
[ -x /bin/sh ] && echo '-x /bin/sh'

数値比較

one=1
two=2
[ $one -eq 1 ] && echo '$one -eq 1'
[ $one -ne $two ] && echo '$one -ne $two'
[ $one -lt $two ] && echo '$one -lt $two'
[ $one -le $two ] && echo '$one -le $two'
[ $two -gt $one ] && echo '$two -gt $one'
[ $two -ge $one ] && echo '$two -ge $one'

Parameter Expansion

string=abcdef
echo ${string}   # abcdef
echo ${#string}  # 6

部分列

# ${parameter:offset}
# ${parameter:offset:length}
echo ${string:0:3}  # abc
echo ${string:1:3}  # bcd
echo ${string:2}    # cdef
echo ${string: -2}  # ef

置換

文字列の置換には正規表現を使える sed が便利。 でもパスや拡張子のちょっとした操作なら、 わざわざ外部コマンドやパイプを使わずにシェル(bash)の機能だけで実現できる。

# ${STR#pattern}        # sed -e "s/^pattern//")     shortest
# ${STR##pattern}       # sed -e "s/^pattern//")     longest
# ${STR%pattern}        # sed -e "s/pattern$//")     shortest
# ${STR%%pattern}       # sed -e "s/pattern$//")     longest
# ${STR/pattern/repl}   # sed -e "s/pattern/repl/")  longest
# ${STR//pattern/repl}  # sed -e "s/pattern/repl/g") longest
# ${STR/#pattern/repl}  # sed -e "s/^pattern/repl/") longest
# ${STR/%pattern/repl}  # sed -e "s/pattern$/repl/") longest

FILEPATH=/root/dir/file.tar.gz
echo ${FILEPATH##*/}       # file.tar.gz
echo ${FILEPATH##*.}       # gz
echo ${FILEPATH#*.}        # tar.gz
echo ${FILEPATH%/*}        # /root/dir
echo ${FILEPATH%.*}        # /root/dir/file.tar
echo ${FILEPATH%%.*}       # /root/dir/file
echo ${FILEPATH/%.*/.zip}  # /root/dir/file.zip

変数が設定されていない場合にどうするか

              # if VAR is null, then
${VAR:-WORD}  # return WORD; VAR remains null
${VAR:=WORD}  # return WORD; WORD is assigned to VAR
${VAR:?WORD}  # display error and exit
${VAR:+WORD}  # nothing occurs; otherwise return WORD

Arrays

bashとzshで添字の挙動が異なる。

array=(a b c d e f)  # bash        | zsh
echo ${array}        # a           | a b c d e f
echo ${array[0]}     # a           |
echo ${array[1]}     # b           | a
echo ${array[-1]}    # (error)     | f
echo ${array[@]}     # a b c d e f | a b c d e f
echo ${#array}       # 1           | 6
echo ${#array[@]}    # 6           | 6

文字列と同様にコロンを使う方法ならzshでもゼロ基準なので安全。

echo ${array[@]:0:3}  # a b c
echo ${array[@]:1:3}  # b c d
echo ${array[@]:2}    # c d e f
echo ${array[@]: -2}  # e f

array[*]array[@] はクオートで括られる挙動が異なる。 前者はひと括り、後者はそれぞれ括られる。

for x in "${array[*]:3}"; do
  echo $x
done
# d e f

for x in "${array[@]:3}"; do
  echo $x
done
# d
# e
# f

Special Parameters

$0        # The full path of the script
$1        # First argument
$#        # The number of arguments ($0 is not included)
$*        # 全ての引数。"$*" はひと括り: "$1 $2 $3"
$@        # 全ての引数。"$@" は個別括り: "$1" "$2" "$3"
$-        # シェルの起動時のフラグ、setコマンドを使って設定したフラグの一覧
$$        # シェル自身のプロセスID
$!        # シェルが最後に起動したバックグラウンドプロセスのプロセスID
$?        # 最後に実行したコマンドのexit値

Misc.

Command

コマンドの結果を文字列として受け取る方法は `command` と $(command) の2つあるが、 後者のほうが入れ子など柔軟に使える。

Arithmetic

足し算くらいなら $((expression))

関連書籍