関数を生成する関数を作成しようとしています。外部関数に渡された内容に基づいて、内部関数のパラメータを「ハードコーディング」したいと思います。例えば
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; }" ); }