例えば、表を引いて値を変換しなければならないといったケースでは、sh スク リプトで1次元配列が欲しくなるときがあります。
korn sh や最近の bash では1次元配列をサポートしていますし、複雑な操作な ら、awk や perl といった外部のプログラミング言語を起動するのが簡単ですが、 /bin/sh や POSIX 1003.1 の sh の枠組でも、位置パラメータを使うと、比較的 素直な扱いができます。
例えば、12 の要素 Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec を持つ1次元配列を考え、そのインデックスを 1, 2, 3, .. 12 とします。この 配列の i 番目の要素を変数 v の値として取り出す操作として最も簡単なのは、 次の方法ではないかと思います。
i=8 # 例えば、8 番目の要素を v に代入する if [ $i -lt 1 -o $i -gt 12 ] then echo "i の値が範囲外 (1 - 12)" exit 1 fi set dummy Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec shift $i v=$1 echo $v変数 i には 1 から 12 のインデックス値を入れておきます。dummy は、i の値 をデクリメントしなくても良いようにするための仕掛けです。
eval を使えば、次のように直接 i 番目の要素を取り出すこともできます。
i=8 # 例えば、8 番目の要素を v に代入する if [ $i -lt 1 -o $i -gt 12 ] then echo "i の値が範囲外 (1 - 12)" exit 1 fi set Jan Feb Mar Apr May Jun Jul Aug Aep Oct Nov Dec if [ $i -ge 10 ] then i=`expr $i - 9` shift 9 fi v="v=\$$i" eval $v echo $v
上記と同じ配列に含まれる特定の値に対応するインデックス値を求める場合は、 もうすこし面倒になりますが、次の方法が素直でしょうか。変数 v には検索し たい要素の値を入れておくと、変数 n に対応するインデックス値が得られます。
v="Aug" # 例えば、Aug が何番目かを求める set Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec n=1 while [ $# -gt 0 ] do if [ $1 = $v ] then break fi n=`expr $n + 1` shift done if [ $# -eq 0 ] then echo "要素 $v は存在しません。" exit 1 fi echo $n
expr を使うのがいやという場合は、次のような方法もあります。
v="Aug" # 例えば、Aug が何番目かを求める set Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec n=1 while [ $# -gt 0 ] do if [ $1 = $v ] then break fi n="$n x" shift done if [ $# -eq 0 ] then echo "要素 $v は存在しません。" exit 1 fi set $n n=$# echo $n
# 年月から、その月の末日を求める y=`/bin/date +%Y` # 年 m=`/bin/date +%m` # 月 set 31 28 31 30 31 30 31 31 30 31 30 31 if [ `expr $y % 4` -eq 0 -a `expr $y % 100` -ne 0 -o `expr $y % 400` -eq 0 ] then set 31 29 31 30 31 30 31 31 30 31 30 31 fi if [ $m -ge 10 ] then m=`expr $m - 9` shift 9 else m=`expr $m + 0` fi eval dmax=\$$m # 月の末日 echo $dmax
平林 浩一, 1997-08-14