
複数のパラメーターを含むコマンドがあります。
my_command --arg1 <arg1> \
--arg2 <arg2> \
--arg3 <arg3>
my_command
渡されても渡されなくてもよい、さまざまなパラメータの値を設定する関数で呼び出しをラップします。
run_my_command() {
if [[ ... ]]; then
ARG1FLAGS="--arg1 $ARG1"
else
ARG1FLAGS=''
fi
if [[ ... ]]; then
ARG2FLAGS="--arg2 $ARG2"
else
ARG2FLAGS=''
fi
if [[ ... ]]; then
ARG3FLAGS="--arg3 $ARG3"
else
ARG3FLAGS=''
fi
my_command $ARG1FLAGS \
$ARG2FLAGS \
$ARG3FLAGS
}
場合によっては、ファイル名引数を次に渡す必要がありますmy_command
。
run_my_command() {
# ...
if [[ ... ]]; then
FILEARG="--input_file $SOME_FILE"
else
FILEARG=''
fi
my_command $FILEARG \
...
}
これらすべてがうまくいきます。これで、条件付きでプロセス置換を使用したいのですが、FILEARG
当然動作しません。
run_my_command() {
# ...
if [[ ... ]]; then
FILEFLAG='--input_file'
FILEARG=<(other_cmd)
else
FILEARG=''
fi
my_command $FILEFLAG $FILEARG \
...
}
ランタイムによってmy_command
匿名$FILEARG
パイプのように見えるのが/dev/fd/63
閉じたからです。
今、すべてを条件付きで入れて、my_command
この問題を解決しました。
run_my_command() {
# Get ARG1, ARG2, ARG3...
if [[ ... ]]; then
my_command --input_file <(other_cmd) \
$ARG1FLAGS \
$ARG2FLAGS \
$ARG3FLAGS
else
my_command $ARG1FLAGS \
$ARG2FLAGS \
$ARG3FLAGS
fi
}
しかし、私は繰り返しが好きではありません。を使って何かをしたり、他の関数eval
に入れることができるようですが、my_command
まだ把握していません。my_command
呼び出し全体を複製せずに読み取り可能なファイルを生成するために条件付きでプロセス置換を使用するにはどうすればよいですかmy_command
?
私はbash 4.4.19を実行しています。驚いたことに、bash 3.2.57は以下のBash Hackers Wikiで提案された方法で動作するようです。
doit() {
local -r FOO=<(echo hi)
cat $FOO
}
doit
# bash 3.2.57:
$ ./test.sh
hi
# bash 4.4.19:
$ ./test.sh
cat: /dev/fd/63: Bad file descriptor
以下は私が確認した質問ですが、次から有効な答えを得ることはできません。
さらに、バッシュハッカーウィキノートむしろ神秘的に:
プロセス置換が関数への引数、関数呼び出し中の環境変数、または関数内の割り当てに拡張されると、プロセス置換は、関数内または呼び出されるすべてのコマンドで使用できるように「開いたまま」になります。またはそれを設定した関数が返されるまで。呼び出し先で同じ変数がリセットされると、新しい変数がローカルでない限り、以前のプロセス置換が解放され、呼び出し先が返されたときに呼び出し側は変数を使用できません。
デフォルトでは、関数内変数に展開されるプロセス置換は、プロセス置換が発生する関数が返されるまでオンになっています。これは、関数呼び出し元が設定したローカル変数に割り当てられている場合も同様です。ダイナミックレンジは閉じることを防ぎません。
ただし、関数の変数にプロセス置換を割り当てるだけでは、「開いたままにする」ことはできません。
答え1
これは質問と似ていますが、他のパラメータを単一の変数ではなく配列に入れると、重複が減ります。$ARGnFLAGS
いずれにせよ、これは単語の分割やファイル名のグロービングを中断することなくコマンドの引数を取得できるため、これは正しいことです。
run_my_command() {
args=()
if [[ ... ]]; then
args+=(--arg1 "$ARG1")
fi
if [[ ... ]]; then
args+=(--arg2 "$ARG2")
fi
if [[ ... ]]; then
my_command --input_file <(other_cmd) "${args[@]}"
else
my_command "${args[@]}"
fi
}
答え2
run_my_command() {
# ...
if [[ ... ]]; then
tmpfile=$(mktemp)
trap 'rm -f "$tmpfile"' RETURN
other_cmd >"$tmpfile"
FILEFLAG='--input_file'
FILEARG="$tmpfile"
else
FILEARG=''
fi
my_command $FILEFLAG $FILEARG \
...
return
}
...またはそのようなもの。
つまり、プロセス置換を使用する代わりに一時ファイルを使用します。
答え3
次の方法を使用して必要なものeval
を取得できます。
run_my_command() {
# Get ARG1, ARG2, ARG3...
commandline="my_command $ARG1FLAGS $ARG2FLAGS $ARG3FLAGS"
if [[ ... ]]; then
commandline="$commandline --input_file <(other_cmd)"
fi
eval $commandline
}