bashでコマンドライン引数を複数取得する方法を間違えて認識していた

これまで気づかなかった方が不思議なのだけど、ハマって解決したのでメモ。

.bashrcに自作関数fooを作って、ターミナルから呼び出す際に、引数としてbar1, bar2, bar3を入れるという場合。

受け取り側では、今までこんな感じで関数を書いていた。

function foo {
    local arg="$@"
    echo $arg
}

これでこのように呼び出すと、

$ foo bar1 bar2 bar3

このように出る。

bar1 bar2 bar3

だから当然、この中のbar2を取り出したいと思ったら、関数にはこのように書けばいいのだと思っていたけど、

function foo {
    local arg="$@"
    echo ${arg[1]}
}

実行しても何も出てこない。

おかしい・・と思ってこのようにプリントデバッグしてみると、

function foo {
    local arg="$@"
    echo all: ${arg[@]}
    echo arg0: ${arg[0]}
    echo arg1: ${arg[1]}
}

こんな感じ。

all: bar1 bar2 bar3
arg0: bar1 bar2 bar3
arg1:

ひとつ目の要素に全部入ってるんですね〜・・😇

で、しばらくハマっていましたが、関数内での引数の受取り時に、配列として受け取ればよかったようです。

function foo {
    local arg=("$@") # <= New!
    echo all: ${arg[@]}
    echo arg0: ${arg[0]}
    echo arg1: ${arg[1]}
}

実行。

all: bar1 bar2 bar3
arg0: bar1
arg1: bar2

OK!

んーむ、引数を用いた.bashrc内の関数、少なくとも3年は使ってきた(書いてきた)と思うんだけど、全然気づいてなかった・・。