2013-12-03

配列(その2) - Bash Advent Calendar - Day 2

すでに時間ギリギリ。さて、昨日は初期化と代入を説明したので、今日は削除と参照をば。

削除

変数まるごと削除は unset で。
$ foo=("bar" "baz")
$ unset foo
$ declare -p foo
bash: declare: foo: 見つかりません

特定の要素を削除するには unset 変数[インデックス]で。
$ foo=("bar" "baz")
$ unset foo[0]
$ declare -p foo
declare -a foo='([1]="baz")'

削除については以上。よほど大規模な Bash スクリプトでもない限り、unset とかわざわざ使うこともないでしょう。

参照

これだけでかなりの量を書ける気がするのですが、二日目にして既に息切れ状態なので手短に。

もう日本語が面倒になってきたので、以下の例参照。
$ foo=("bar" "baz")
$ echo ${foo[0]}
bar
$ echo ${foo[1]}
baz
$ echo ${foo}
bar
$ unset foo[0]
$ echo ${foo}
    # 何もなし
というわけで、${変数[インデックス]} で参照できます。インデックスを省略した場合、それは [0] と等価(最小インデックスを参照してくれるわけではない)になります。どうがんばって見ても、インデックス指定なしの参照は配列変数にアクセスしているようには見えないので、変に省略するのはやめましょう。もとい、そんな変な仕様知ってる人なんてほとんどいないでしょう。

すべての要素を参照

ここまではウォームアップです。これから実用性アップのはず。

さて、配列にまとめてアクセスするには * もしくは @ という特殊なインデックスを使います。
$ foo=("bar" "baz")
$ echo "${foo[*]}"
bar baz
$ echo "${foo[@]}"
bar baz
この例では * と @ に違いがありませんが、その違いは "$*" と "$@" の違いと一緒です。

わからない人にとっては何言ってるのか意味不明だと思いますが、これはこれで一日分使えるのでまたの機会に。とりあえず、IFS を変更しない限り @ の方を使うと覚えておけば大丈夫です。

これを応用することで、配列のコピーができます。
$ foo=("bar" "baz")
$ qux=("${foo[@]}")
$ declare -p qux
declare -a qux='([0]="bar" [1]="baz")'
これは2行目の qux= の部分が
$ qux=("bar" "baz")
と変数展開された結果です。さて、初期化の部分で述べたように、Bash の配列はインデックスが飛び飛びでも構わないのですが、変数展開ではインデックスの値までは展開されないので、このコピーは完璧ではありません。

インデックスの参照

というわけで、格納されてるインデックスを参照したくなりますよね。
$ foo=("bar" "baz")
$ echo "${!foo[@]}"
0 1
$ unset foo[0]
$ echo "${!foo[@]}"
1
というように "${!変数名[@]}" でインデックスをまとめて取り出せます。ここでも * と @ を使えますが、その違いについては割愛します。ここでもとりあえず @ で覚えておけば間違いありません。

このテクニックを使えばコピーも完璧です。
$ foo=([1]="bar" [3]="baz")
$ qux=()
$ for i in "${!foo[@]}"; do
$   qux[i]="${foo[i]}"
$ done
$ declare -p qux
declare -a qux='([1]="bar" [3]="baz")'
 力尽きたので、さらに明日に続きます。
 



0 件のコメント:

prometheusのrate()関数の罠

 久しぶりのAdventカレンダー挑戦、うまくいく気がしません。 閑話休題。実のところ、rate()関数というよりは、サーバー側のmetric初期化問題です。 さて、何らかのサーバーAがあったとして、それが更に他のサーバーBにRPCを送っているとします。サーバーBの方でホワイトボ...