
次のような(無意味な)Bash関数があるとしましょう。
myfunc() {
ls
failfailfail
uptime
}
私は次のように実行します:
myfunc || echo "Something is wrong."
私が望むのは、ls
実行されなければならないので、動作せずfailfailfail
(存在しないので)uptime
実行されないことです。関数の戻り値はゼロではなく、エラーメッセージが表示されます。戻り値は、失敗したコマンドの正確な終了状態である必要はなく、単にゼロにしてはいけません。
実際に起こるのは、出力を取得してls
から「-bash:failfailfail:command not find」、そして「-bash:failfailfail:command not find」の出力を取得することですuptime
。失敗したシャットダウン状態が悪いため、エラーメッセージは表示されません。
set -e
関数内や呼び出し関数の範囲では有用な効果はありません。私が望む方法で動作させることができる唯一の方法は次のとおりです。
myfunc() {
ls || return $?
failfailfail || return $?
uptime || return $?
}
しかし、これは非常に反復的で醜いようです。これをきれいにする他の方法はありませんか?
答え1
でなければ、set -e
スクリプトfailfailfail
全体(または関数がサブシェルで実行されている場合はサブシェル)が終了します。
関数でシェルの状態を変更する必要がない場合は、サブシェルで実行できます。
myfunc() (
set -e
ls
failfailfail
uptime
)
Bashのもう一つの方法は次のとおりです。ERR
罠実装するreturn
。ローカル設定にするには、古いトラップ値を復元する必要がありますが、これは少し面倒です。
myfunc() {
local old_ERR_trap=$(trap -p ERR)
if [[ -z $old_ERR_trap ]]; then old_ERR_trap="trap - ERR"; fi
trap 'local ret=$?; eval "$old_ERR_trap"; return $ret' ERR
ls
failfailfail
uptime
}
答え2
簡単にする唯一の方法は、すべてを1つのコマンドにまとめることですが、これは以前のバージョンよりもスクリプトを維持するのが難しくなります。
myfunc() {
ls && failfailfail && uptime || return $?
}
答え3
単純なコマンドであることを考慮すると、次のようにすることができます。
myfunc() {
ls &&
failfailfail &&
uptime ||
return $?
}
答え4
時にはそのようなことを処理できるMakefileに内容を入れる方が良い場合もあります。
#!/bin/bash
myfunc() { # watch out for tabs!
make -f - <<!
default:
ls -d
failfailfail
uptime
!
}