配列を関数パラメータとして渡しますが、他の追加パラメータを使用するには?

配列を関数パラメータとして渡しますが、他の追加パラメータを使用するには?

次の投稿解決策期待どおりに動作します。

だから - 彼の答えで判断すると:

function copyFiles() {
   arr=("$@")
   for i in "${arr[@]}";
      do
          echo "$i"
      done

}

array=("one 1" "two 2" "three 3")

copyFiles "${array[@]}"

この記事を書く理由は、次のような場合に何をすべきかです。

copyFiles "${array[@]}" "Something More"
copyFiles "Something More" "${array[@]}"

質問:送信された引数と受信された引数が関数にあることを知っています。実際にはマージされているため、$1$2配列」パラメータは期待どおりに機能しなくなります。統合別の主張で

私は研究しました:

typeset -n悲しいことにいいえ働く

そして:

するいいえ${#array[@]}期待どおりに動作します。この回答には、関数内で配列サイズ()が異なる場合のデモテスト/検証リンクで問題があるという説明があります。

それでは、この目標を達成する方法は?

答え1

このように、配列をパラメータとして渡すことはできません。したように見えますが、期待どおりに機能しません。

あなたのシェル(例:ここ:)は個々のプロジェクトにbash拡張されます。"${array[@]}"今後機能を実行してみてください!

だからこれ

copyFiles "Something More" "${array[@]}"

実際に電話をかける

copyFiles "Something More" "one 1" "two 2" "three 3"

したがって、関数内の他のパラメータと配列を区別することは不可能です。

(あなたできる 配列への参照を追加するしかし、移植性が低下しているように見え、必要でない場合は範囲​​を混在させたくないので、使用しないことをお勧めします。


shiftたとえば、を使用できます。

copyFiles() {
    var1=$1
    shift
    for i in "$@"; do ... ; done
}

(これはarr=("$@")重複してすでに配列なので、$@指定する必要はなく、"$@"単に使用することもできますfor i; do ...; done。)

または、次のパラメータを解析します。getopts

答え2

これを直接行うことはできず、とにかくあまり良くありません。配列は実際にはBashの一流のオブジェクトではありません。

重要な問題は、"${array[@]}"実際に配列自体を提供するのではなく、配列のすべての要素(リスト)に拡張することです(インデックス付けを忘れてください!)。

確かにいくつかの解決策がありますが、これが非常に良いと言えるかどうかはわかりません。しかし、あなたはできます...

  1. いくつかの区切り記号を使用してください。

    func "non-array" "arguments" :: "${array[@]}" 
    

    これは本質的にGNU Parallelが行うことですが、実際のパラメータとして使用できないいくつかの値を決定する必要があるという欠点があります。 (またはそれをエスケープする方法はおそらくより悪いでしょう。)区切り文字を見つけるには、パラメータリストをスキャンする必要があります。

  2. リストの長さを示すパラメータを追加します。

    func 1 "non-array argument" "${#array[@]}" "${array[@]}" 
    

    これは有効な値を渡すのに十分一般的でなければなりませんが、Cでの手動メモリ処理の痛みを伴う記憶を呼び起こし始めても、私はあなたを責めることはありません。もう一方の端で構文解析することは、それをしたいほど狂った人には練習の役割もします。

  3. 代わりに名前で配列を渡します。

    たとえば、次のようにnamerefを使用できます。

    fun() {
        local _arrayname="$1"
        local -n _ref="$1"
        printf "array '%s' has %d members\n" "$_arrayname" "${#_ref[@]}"
        printf "member at index #2 is '%s'\n" "${_ref[2]}"
    }
    asdf=(one too tree)
    fun asdf
    

    間接構文を使用してみることもできますが、${!p}IIRCでは、配列索引付けはその構文を使用するのがより困難です。もちろん、両方とも移植不能なので、Bashを使用することができますが、Bashはバージョン4.4以降から名前参照をサポートしているため、ほとんどの場合問題にはなりません。

    namerefsの問題は名前空間の競合です。上記の関数に_arraynameorという名前の配列を渡すことはできません。_ref

関連情報