シェル変数まとめ

シェル変数を展開方法や、位置パラメータ、特殊変数の存在をよく忘れてしまうので、まとめておく。
変数の展開方法と特殊変数は、数が多いので有用そうなものだけまとめる。


ただ、今回まとめた内容は、主にシェルスクリプトで用いることになると思う。
憶えにくい、タイプ数の多い表記が沢山あるので。

動作を確認した環境

  • zsh (5.0.5)
  • bash(POSIXモード) (4.3.11)
  • mksh (49-1)
  • dash (0.5.7-4)

概要

  • シェル変数の展開
  • 位置パラメータ
  • 特殊シェル変数

解説

シェル変数の展開

シェル変数の値をセットする際、変数の使用状況・条件に応じて、セットする値や展開したときの表示を、変更することができる。
条件に応じて変数を設定する主な方法は、以下の通り。

  1. ${variable:=value}
  2. ${variable:-value}
  3. ${variable:?message}
  4. ${variable:+value}
  5. ${variable#pattern}
  6. ${variable##pattern}
  7. ${variable%pattern}
  8. ${variable%%pattern}
  9. ${variable/pattern/new}
  10. ${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をそのまま返す。

$ echo ${VAR:-hoge}
hoge # 表示される内容は = を使った時と同じ
$ echo $VAR
$ # ただし変数VARには値hogeが代入されていない
${variable:-value}は、値を変数に代入しないので、位置パラメータのように書込み禁止の変数に用いることができる。また、スクリプトのデフォルト値を設定する際にも有用である。

${variable:?message}
変数variableを展開する際、variableがこれまで未使用である、もしくはヌルである場合、messageを表示する。
${variable:?message}は、変数が未使用、もしくはヌルであるかどうかを確認するために使う。

${variable:+value}
変数variableに値が設定されている場合、設定されている値の代わりにvalueを表示する。variableの元の値は変更しない。また、variableが未使用、もしくはヌルである場合は、何もしない。

$ VAR=piyo # 変数VARに値piyoをセット
$ echo $VAR
piyo
$ echo ${VAR:+hoge}
hoge # 値piyoの代わりにhogeが表示される
$ echo $VAR
piyo # しかし元の値は変更されていない
${variable:+value}は、変数の値を変更せずに、展開した時の値を一時的に変えたい場合に使う。

${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種類。

  1. $0
  2. ${1..9}
  3. $#
  4. $*
  5. $@
  • 位置パラメータを使う上での注意点
    • 位置パラメータは、$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種類。

  1. $?
  2. $$
  3. $!
  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. Bruce Blinn、山下哲典(訳):入門UNIXシェルプログラミング 改訂第2版、pp.40-56、Softbank Creative(2003)
  2. 広瀬雄二:zshの本、pp.195-201、技術評論社(2009)

雑記

  • "=-?+"を使ったシェル変数の設定は、ややこしくて憶えにくい。参考書籍1にも書いてあるけれど、可読性を良くするなら、if文で代用したほうが良いかもしれない。
  • 変数の展開には、値の柔軟な変更ができる${variable:#pattern}もある。けれど、zshしか使えない上に、動作を変更できるフラグが非常に多いので、今回は割愛。