以下は推奨される回避策です。私はそれを実行し、効果があった。
#!/bin/bash
function exit_handler() {
local device_name="${1}"
echo "Exit handler: ${device_name}"
}
function other() {
echo "Other: ${device_name}"
}
function do_something() {
local device_name="abc"
trap "exit_handler '${device_name}'" EXIT
other
}
do_something
# (my comment) I am assuming an implied exit here
実際には、コメントアウトされたコマンドラインに端末の実際のシャットダウンを入力しました。
次の質問があると、それは何であり、なぜ機能するのか理解できません。
質問1 - 与えられた内容:
trap "exit_handler '${device_name}'" EXIT
$ {device_name}の周りの一重引用符は、トラップが開始されたとき(ハンドラが終了した後に「do_something」が返され、ローカル変数$ {device_name}がもう存在しなくなった後)、置換を実行する必要があることを示します。 、私の考えでは、)コードに終了ステートメントがなく、終了の明確なエラー理由がないためです。置換を満たすには、「do_something」関数を返す必要があり、$ {device_name}変数はもう存在しません。ステートメントが単一引用符なしで次のように再コーディングされる場合
trap "exit_handler ${device_name}" EXIT
シャットダウンが発生するずっと前にTrapステートメントが実行されたときに置換がどのように発生するかを明確に知ることができます。ここでbashリファレンスが何であるか理解できませんか?
質問2 - "do_something"に次の文が与えられました。
other
「do_something」に対してローカルと見なされ、「other」が明らかに「do_something」でない場合、「do_something」で呼び出された「other」関数に$ {device_name}のローカル値を使用できるようにする特別なスコープルールがありますか? ? 「何かをしなさい」の地域的価値は?私は他の言語のスコープルールがこれを防ぐと思います。以下に示すように、${device_name}をパラメータとして要求する関数呼び出し(トラップ呼び出しなど)が必要です。
other "${device_name}"
「その他」はローカル変数にパラメータを割り当てる必要があります。
local device_name="${1}"
明らかに、Bashのスコープ指定を理解していません。
答え1
このコードを実行すると、
local device_name="abc" trap "exit_handler '${device_name}'" EXIT
シェルは二重引用符を見て、$()
その中の変数と式を評価します。
device_name="abc"
trap "exit_handler 'abc'" EXIT
その後、シェルは結果を実行して終了トラップを設定します。 (if)トラップがトリガされると、exit_handler
関数は単一の3文字引数で呼び出されますabc
。
あなたの声明、」${device_name}の周りの一重引用符は、(とにかく私に)トラップを開始するときに置き換えが行われるべきであることを示します。「は正しくありません。完全な式の周囲の二重引用符は、シェルが見て評価する内容を制御します。文字列内の一重引用符は、この時点で単なる一般的な文字です。
$device_name
トラップパラメータの評価を遅らせるには、単一引用符で囲んで渡す必要があります。
#!/bin/bash
exit_handler() {
local device_name="$1"
echo "Exit handler: $device_name"
}
other() {
echo "Other: $device_name"
}
do_something() {
local device_name="abc"
trap 'exit_handler "$device_name"' EXIT
other
}
do_something