シェルスクリプトで何かのコマンドを実行したい場合、そのコマンドの実行前後に他の処理を入れたり、コマンドに特定のオプションをつけたりしたいことが出てくることがあります。他にも、メインの関数の前に他の関数を挟んだりしたいこともあります。この場合、本来実行したいコマンドや関数のラッパー関数を作ることになります。

ラッパー関数を作りたい場合その関数の引数全部を「$@」という特別な変数を参照できますが、この変数は配列です。そのため「$@」を他の変数にそのまま代入したい場合、そのまま参照すると想定外の挙動になるので、以下のように代入しましょう。

ARGS=("$@")

上記で代入するとARGSは配列になるので、各引数も以下のように取り出せます。

ARG1=${ARGS[0]}
ARG1=${ARGS[1]}

ラッパー関数なので、本来実行したい関数やコマンドにそのまま引数で渡したい場合も、配列として全要素を渡しましょう。

myfunc.sh

#!/bin/bash

function main {
    echo "---- main ----"
    local ARGS=("$@")
    echo "arg1=${ARGS[0]}"
    echo "arg2=${ARGS[1]}"
    echo "arg3=${ARGS[2]}"
    echo "arg4=${ARGS[3]}"
}

function myfunc {
    echo "---- myfunc ----"
    local ARGS=("$@")
    echo "arg1=${ARGS[0]}"
    echo "arg2=${ARGS[1]}"
    echo "arg3=${ARGS[2]}"
    echo "arg4=${ARGS[3]}"

    main "${ARGS[@]}"
}

myfunc "a b" c "d" "e f g"
$ ./myfunc.sh
---- myfunc ----
arg1=a b
arg2=c
arg3=d
arg4=e f g
---- main ----
arg1=a b
arg2=c
arg3=d
arg4=e f g
やりがちなミス

ARGS代入時に$@をダブルクォーテーションで囲み忘れると、引数にスペースが入っている場合に想定外の動作をするのでご注意ください。

myfunc.sh

#!/bin/bash
function myfunc {
    local ARGS=($@)
    echo "arg1=${ARGS[0]}"
    echo "arg2=${ARGS[1]}"
    echo "arg3=${ARGS[2]}"
    echo "arg4=${ARGS[3]}"
    echo "arg5=${ARGS[4]}"
    echo "arg6=${ARGS[5]}"
    echo "arg7=${ARGS[6]}"
}

myfunc "a b" c "d" "e f g"
$ ./myfunc.sh
arg1=a
arg2=b
arg3=c
arg4=d
arg5=e
arg6=f
arg7=g

逆にARGSに配列として代入しないと、以下のように引数全体が一つの文字列になってしまいます。

myfunc.sh

#!/bin/bash
function myfunc {
    local ARGS="$@"
    echo "args=${ARGS}"
    echo "arg1=${ARGS[0]}"
    echo "arg2=${ARGS[1]}"
}

myfunc "a b" c "d" "e f g"
$ ./myfunc.sh
args=a b c d e f g
arg1=a b c d e f g
arg2=