Bash関数の内部:外部関数から特定の変数を挿入する方法

Bash関数の内部:外部関数から特定の変数を挿入する方法

関数を生成する関数を作成しようとしています。外部関数に渡された内容に基づいて、内部関数のパラメータを「ハードコーディング」したいと思います。例えば

outer() {
    inner() { doSomething --context=$1 $@ }
}

上記の内容を参考に電話してください。

outer foo

内部関数を次のように定義したいと思います。

inner() { doSomething --context=foo $@ }

つまり、内部関数定義に外部関数の$ 1を挿入しますが、内部関数呼び出し時に挿入のために$ @を保持します。

この目標をどのように達成できますか?


編集する、私のユースケースが気になる人のために:

サブコマンドを含むコマンドラインツールを使用しています。例えば

doSomething dothis somearg
doSomething dothat

しかし、常にコンテキストフラグが必要です。例えば

doSomething --context foo dothis somearg
doSomething --context foo dothat

通常、コンテキストを入力すると、次のいくつかのコマンドは同じコンテキストを使用します。

したがって、理想的なソリューションを使用すると、コンテキストを一度設定し、コンテキストが既に知られているエイリアスのように内部関数を使用できます。

outer foo
inner dothis somearg
inner dothat

これは環境変数を介して行うこともできます。例えば

alias inner="doSomething --context=$CONTEXT"

しかし、実際には1つではなく2つのフラグがあります(これは現実的なパラメータを使用して)。

outer gke_gke-xpn-1_europe-west1_europe-west1-s41l stats_service
inner dothis somearg
inner dothat

—— (私にとって) —— よりユーザーフレンドリーです。

CONTEXT=gke_gke-xpn-1_europe-west1_europe-west1-s41l
NAMESPACE=stats_service
inner dothis somearg
inner dothat

答え1

関数を生成する関数を作成しようとしています。外部関数に渡された内容に基づいて、内部関数のパラメータを「ハードコーディング」したいと思います。

あなたが望むものはクロージャですが、Bashにはそのようなクロージャがないと思います。

内部関数が実行される「コンテキスト」として別のグローバル変数を使用するだけです。例えば

context=
outer() {
    context=$1
}
inner() {
    if [ -z "$context" ]; then
        echo "context not defined" >&2
        return 1;
    fi
    doSomething --context="$context" "$@"
}

2つのコンテキスト変数が必要な場合は、別の変数を追加するだけです。

両方を引用し"$context""$@"スペースやワイルドカードを含む値が単語の分離によって破損していないことを確認する必要があります。

答え2

まあ、私は実際に1時間の悩みの終わりに見つけました。重要なことは、eval補間を遅らせる必要がある変数を使用してエスケープすることです。もっと良い方法があれば知りたいです!答えを追加してください。

#!/bin/bash
outer() {
    eval "inner() { doSomething --context=$1 \$@ }"
}

答え3

Bashでは、次のように実行されます。

#!/bin/bash
outer() {
    # define inner function
    inner() {
        echo 1=$1 2=$2 
    }

    # call inner function
    inner $1 $2
}

# this would give an error, 
inner foo 123

# call outer function.
outer bar 456

# now the inner function is defined and ready to be used by itself
inner baz 789

答え4

では、bash次のように動作します。

outer() { . <( echo "inner() { doSomething $1 $2;  }" ); }

関連情報