ファイヤープロジェクト
展開
2003-07-26T11:21+09:00   matsu
BASHの変数展開機能は豊富で使いこなせると効率的なプログラミングができる.ただし,BASH独自の機能が多いので,他のシェルスクリプトへの移植性が下がる.
何かを入力したとき,それが何なのかを突き止めてくれる,それが展開である.
ls $HOME
とした場合,$HOMEが何なのかを突き止めて(この場合,変数の値を調べて),
ls /home/hoge
としてくれるのが展開である.
あるコマンドに引数に別のコマンドの実行結果を代入することができる.それには$(command)とする.以下に例を示す.
set $(date)
while [ "$1" != "" ]
do
echo $1
shift
done
これを実行すると,パラメータ変数にdateコマンドの実行結果が割り当てられ,それらを順に表示する.setコマンドの引数にdateコマンドの出力が渡されているのである.
evalコマンドは引数を読み込んで一つのコマンドを生成する.そしてそのコマンドを実行する.以下に例を示す.
a=date
eval b='$('$a')'
echo $b
まずaにdateという文字列を代入する.evalコマンドにはまず変数aが展開されてb=$(date)が渡される.そしてevalコマンドはb=$(date)というコマンドを実行する.そして最終的にbにdateコマンドの出力が代入され,その値がechoコマンドによってbの値が出力去れる.もしevalがなければbの値は$(date)という文字列になってしまう.
この例を応用していくと,変数に動的に代入された,コマンドを示す文字列を実行することができる.
算術展開は計算をして,その値に展開してくれる.算術展開は$((式))である.例を以下に示す.
x=10
echo $(($x+$x))
これを実行すると10+10が計算されて20と出力される.
変数展開は本ページ冒頭の例である.ここではその応用を述べる.変数aの値に文字列を付加するには以下のようにする.
${a}文字列
変数名を${}で囲って文字列を付加するのである.例を以下に示す.
a=hoge
echo fuga$a
echo $afuga
echo ${a}fuga
まずaにhogeという文字列を代入する.次にfuga$aをechoする.この場合,どれが変数なのか正しく解釈されecho fugahogeが実行される.次に$afugaをechoする.この場合,afugaが変数だと解釈される.したがってafugaの値がecho出力される.最後の場合は${a}fugaをechoする.この場合,aが変数名でfugaは文字列だと解釈され,echo hogafugaが実行される.
${}は強力で,条件に応じてパラメータに設定する値を変えることができる.以下にそのバリエーションを示す.
${変数:-デフォルト値}
変数が空ならばデフォルト値を設定する.
${変数:=デフォルト値}
変数が存在し,空でなければ変数の値を返す.空ならばデフォルト値を設定しその値を返す.
${変数:?文字列}
変数が空ならばアボートする.
${変数:+文字列}
変数が存在し,空でなければ文字列を返す(変数への代入はない).
${#変数}
変数の値の長さ(文字数)を返す.
${変数%パターン}
変数の値の末尾からパターンと一致する部分を探し,最初に一致した部分から末尾まで(最短一致パターン)を取り除いて表示する.
${変数%%パターン}
変数の値の末尾からパターンと一致する部分を探し,最後に一致した部分から末尾まで(最長一致パターン)を取り除いて表示する.
${変数#パターン}
変数の値の先頭からパターンと一致する部分を探し,先頭から最初に一致した部分まで(最短一致パターン)を取り除いて表示する.
${変数##パターン}
変数の値の先頭からパターンと一致する部分を探し,先頭から最後に一致した部分まで(最長一致パターン)を取り除いて表示する.パターンに*が使用されている場合は,*を最大にしたパターンが一致する.
最後の4つは少し分かりにくいので例を示す.
a=usr/src/linux/arch
とした場合,aの値からパターン*/と一致する部分を先頭から探すと以下が順にマッチする.
  • usr/
  • usr/src/
  • usr/src/linux/
これらのうち最初にマッチするのがusr/なので,これを除いた部分が${a#*/}の出力である.そして最後にマッチするのがusr/src/linuxなので,これを除いた部分が${a##*/}の出力である.
次にaの値からパターン/*と一致する部分を末尾から探すと以下が順にマッチする.
  • /arch
  • /linux/arch
  • /src/linux/arch
これらのうち最初にマッチするのが/archなので,これを除いた部分が${a%/*}の出力である.そして最後にマッチするのが/src/linux/archなので,これを除いた部分が${a%%/*}の出力である.
matsu(C)
Since 2002
Mail to matsu