web-dev-qa-db-ja.com

関数呼び出し元の位置パラメーター

関数の呼び出し元の位置パラメーター$@を読み書きする必要があります。 Bashのmanページには次のように書かれています。

シェル関数は、単純なコマンドのように呼び出され、新しい位置パラメーターのセットを使用して複合コマンドを実行するオブジェクトです。

したがって、$@はすべての呼び出しで書き換えられます。 「特別なパラメータ」を探しましたが、何も見つかりませんでした。シェル変数BASH_ARGVは私の問題を解決しているようですが、shopt -s extdebugを有効にする必要があります。私のマシンのデフォルトの動作ではないものは、本番環境でオンにするオプションのようにも見えません。

extdebug
    If set, behavior intended for use by debuggers is enabled:
    ...
    4.     BASH_ARGC and BASH_ARGV are updated as described in their
           descriptions above.
    ...

Bashは、$@なしで関数の呼び出し元BASH_ARGVを読み書きできますか? Bashは制限されており、スクリプトに別のシェルを使用していると思いますか?

編集:ヘルパーライブラリ内に派手なgetoptラッパーが必要です。したがって、それに関連するすべての動作は関数内に入ります。エラーやset --を確認する必要はありません。

6
Pedro Lacerda

関数は、呼び出し元の位置パラメーターに影響を与えることはできません。これは仕様によるものです。位置パラメータは、関数専用にすることを目的としています。

関数を配列で機能させます。

myfunction () {
  local _myfunction_arrayname=$1
  shift
  … # work on the positional parameters
  eval "$_myfunction_arrayname=(\"\$@\")"
}
myfunction foo "$@"
set -- "${foo[@]}"

Ksh93とbashには、エイリアスと組み込みの.source)をプロセス置換と組み合わせることで、何かを近づけるための回り道があります。

alias myfunction='. <(echo myfunction_body \"\$@\"; echo set -- "\"\${new_positional_parameters[@]}\"")'

関数の作業の要点をmyfunction_bodyに入れ、配列new_positional_parametersを設定します。 myfunctionの呼び出し後、位置パラメータはmyfunction_bodynew_positional_parametersに入力する値に設定されます。

ここにいくつかの パラメータをループし、必要に応じて各パラメータを更新するコード 。この場合、重複するスラッシュを単一のスラッシュに置き換えます。

for param
do
    param="$(printf %s. "$1" | tr -s "/")"
    set -- "$@" "${param%.}"
    shift
done
0
l0b0