シェル変数まとめ
シェル変数を展開方法や、位置パラメータ、特殊変数の存在をよく忘れてしまうので、まとめておく。
変数の展開方法と特殊変数は、数が多いので有用そうなものだけまとめる。
ただ、今回まとめた内容は、主にシェルスクリプトで用いることになると思う。
憶えにくい、タイプ数の多い表記が沢山あるので。
概要
- シェル変数の展開
- 位置パラメータ
- 特殊シェル変数
解説
シェル変数の展開
シェル変数の値をセットする際、変数の使用状況・条件に応じて、セットする値や展開したときの表示を、変更することができる。
条件に応じて変数を設定する主な方法は、以下の通り。
- ${variable:=value}
- ${variable:-value}
- ${variable:?message}
- ${variable:+value}
- ${variable#pattern}
- ${variable##pattern}
- ${variable%pattern}
- ${variable%%pattern}
- ${variable/pattern/new}
- ${variable//pattern/new}
1~4の方法は、コロン':'を省略可能である。コロンを入れた場合、変数がこれまで未使用か、ヌルがセットされているときに、コロン以降の処理をおこなう。
コロンを省略した場合、変数がこれまで未使用のときのみ、コロン以降の処理をおこなう。
${variable:=value}
変数variableを展開する際、variableがこれまで未使用である、もしくはヌルである場合、valueを代入してから展開を試みる。
... # 変数VARは一度も使っていない
$ echo ${VAR:=hoge}
hoge # 変数VARは未使用であるが、値hogeが表示される
$ echo $VAR
hoge # 変数VARに値hogeが設定されている
${variable:-value}
変数variableを展開する際、variableがこれまで未使用である、もしくはヌルである場合、valueを代入せずに、valueをそのまま返す。${variable:-value}は、値を変数に代入しないので、位置パラメータのように書込み禁止の変数に用いることができる。また、スクリプトのデフォルト値を設定する際にも有用である。
$ echo ${VAR:-hoge}
hoge # 表示される内容は = を使った時と同じ
$ echo $VAR
$ # ただし変数VARには値hogeが代入されていない
${variable:?message}
変数variableを展開する際、variableがこれまで未使用である、もしくはヌルである場合、messageを表示する。${variable:?message}は、変数が未使用、もしくはヌルであるかどうかを確認するために使う。
${variable:+value}
変数variableに値が設定されている場合、設定されている値の代わりにvalueを表示する。variableの元の値は変更しない。また、variableが未使用、もしくはヌルである場合は、何もしない。${variable:+value}は、変数の値を変更せずに、展開した時の値を一時的に変えたい場合に使う。
$ VAR=piyo # 変数VARに値piyoをセット
$ echo $VAR
piyo
$ echo ${VAR:+hoge}
hoge # 値piyoの代わりにhogeが表示される
$ echo $VAR
piyo # しかし元の値は変更されていない
${variable#pattern}
${variable##pattern}
変数variableの値が、patternで指定したグロッビングパターンにマッチする文字列で始まっていれば、マッチする部分を全て削除した値に展開する。variableの元の値は変更しない。上記2つの違いは、文字列の照合方法。'#'の場合は最短マッチ、'##'の場合は最長マッチで照合をおこなう。
主に、パスの一部を抜出すときに使う。
$ TMPDIR=/home/hoge/tmp
$ echo ${TMPDIR##*/}
tmp
${variable%pattern}
${variable%%pattern}
変数variableの値が、patternで指定したグロッビングパターンにマッチする文字列で終わっていれば、マッチする部分を全て削除した値に展開する。variableの元の値は変更しない。上記2つの違いは、文字列の照合方法。'%'の場合は最短マッチ、'%%'の場合は最長マッチで照合をおこなう。
上記の'#'と組合わせれば、ある文字列の中間部分だけを抜出すこともできる。
${variable/pattern/new}
${variable//pattern/new}
変数variableの値のうち、patternにマッチする部分をnewに置換した値に展開する。variableの元の値は変更しない。上記2つの違いは、文字列の置換方法。'/'の場合は初めにマッチした部分のみを、'//'の場合はマッチすたもの全てを置換する。
簡易sedのように使えるので、様々な場面で役に立つ。
位置パラメータ
位置パラメータを表す変数は、以下の5種類。
- $0
- ${1..9}
- $#
- $*
- $@
- 位置パラメータを使う上での注意点
- 位置パラメータは、$0から$9までの、10個までしか扱えない
- 10個より多くの位置パラメータを使いたい場合は、shiftコマンドを利用して、位置パラメータをずらしていく。
※ 例
$ cat shift_test.sh
#!/bin/sh
shift # 位置パラメータを左に1つずらす
echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9
shift 3 # 位置パラメータを左に3つずらす
echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9
$ sh shift_test.sh a b c d e f g h i j k l m n
hoge.sh b c d e f g h i j
hoge.sh d e f g h i jk l
$0
コマンド自身を表す。${1..9}
第1, 第2, ..., 第9引数を表す。$#
位置パラメータの個数を表す。※ 例
$ cat param_test.sh
#!/bin/sh
echo $#
$ sh param_test.sh hoge piyo hogepiyo
3
$ sh param_test.sh "hoge piyo hogepiyo"
1
$*
$@
引数全体を表す。$*と$@の大きな違いは、ダブルクォートで囲み、展開した場合の動作にある。
$*は、引数全体をダブルクォートで囲んだ状態にして展開する。$@は、引数1個1個をダブルクォートで囲んだ状態にして展開する。
また、位置パラメータが無い場合、$@はヌル、$*は""に置換される。
特殊変数
主要な特殊変数は、以下の4種類。
- $?
- $$
- $!
- $-
$?
コマンド実行時の終了ステータスを表す。ただし、バックグラウンドで実行させたコマンドに対しては無効。終了ステータスは、プログラムに依存するが、大抵の場合は、正常終了:真(0)、異常終了:偽(0以外)の値がセットされる。
$$
現在動作しているコマンドのプロセスIDを表す。プロセスIDは一意であるということを利用して、一時ファイルの命名など、ユニークな番号を付けたい場合に役に立つ。
※ 例
$ touch /tmp/hogehoge.$$
$!
バックグラウンドで実行させたコマンドのプロセスIDを表す。waitコマンドと組合せて、バックグラウンドジョブが終了するのを待ちたい場合に役に立つ。
※ 例
$ rsync -a hoge piyo & # バックグラウンドでrsyncを実行する
... # rsyncが実行している間に、rsyncに依存しない処理をおこなう。
$ wait $! # rsyncが終了するまで待つ
... # rsyncの実行結果に依存する処理をおこなう
$-
シェル起動時オプション、およびsetコマンドを使って設定したオプションの一覧を表す。※ 例
$ echo $SHELL
/usr/bin/dash
$ echo $-
smi # オプション:s, m, iがセットされている
$ set -o vi # オプション:V(vi-keybind)を追加
Vsmi # オプションにVが追加された
参考書籍
雑記
- "=-?+"を使ったシェル変数の設定は、ややこしくて憶えにくい。参考書籍1にも書いてあるけれど、可読性を良くするなら、if文で代用したほうが良いかもしれない。
- 変数の展開には、値の柔軟な変更ができる${variable:#pattern}もある。けれど、zshしか使えない上に、動作を変更できるフラグが非常に多いので、今回は割愛。