true && echo foo
印刷されますfoo
。false && echo foo
印刷されませんfoo
。bash -c "exit $a" && echo foo
foo
に従って印刷されます$a
。
最後のものを書くためのよりエレガントな方法はありますか?終了値を設定するためにシェルを起動する必要があるのはやや面倒です。私は次のことを考えています:
return $a && echo foo
exit $a && echo foo
ただし、return
機能でのみ機能し、決して実行されませexit
んecho foo
。
この場合、優雅さとは次のことを意味します。
- わかりやすい
- 持ち運べる
- 読みやすい
- 使いやすい
- 覚えやすい
- 短い
- 高性能
true
たとえば、終了コードをパラメータ(文書化された機能)として使用すると、非常にエレガントになります。
それでは、もう少しエレガントな方法がありますか?
背景
使用できる場所の1つは次のとおりです。
$ parallel 'setexitval {= $_%=3 =} || echo $?' ::: 0 1 2 3
Kosalonandaのバージョンはおそらく最高です。何が起こったのかは明らかです。文が長くも面倒でもない。覚えやすく持ち運びが簡単です。唯一の欠点は、別のシェルを分岐することです(〜0.5msかかります)。
$ parallel '(exit {= $_%=3 =}) || echo $?' ::: 0 1 2 3
別の状況は、エラー状況をシミュレートする場合です。たとえば、さまざまな終了コードを設定する長期実行プログラムがあり、さまざまな終了コードに反応するいくつかのコードを書いているとします。(exit $a)
長期実行プログラムを実行しなくても、それを使用して条件をシミュレートできます。
答え1
まあ、return
それは関数で動作するので、1つ作ってみましょう。
$ ret() { return "${1-0}"; }
$ ret 1 || echo foo
foo
$ ret 123 ; echo $?
123
サブシェルよりも多くの設定が必要ですが、後で使用する方が短く、サブシェルを分岐する必要はありません。
答え2
指定された値で終了するサブシェルを使用してください。
これにより、次のものが出力されます5
。
a=5; ( exit $a ) && echo foo; echo $?
foo
これにより、次のように印刷されます0
(このゼロはサブシェルではecho
なく後続に設定されます)。exit
a=0; ( exit $a ) && echo foo; echo $?
a
(明白な設定や明示的な調査なし)短縮形式で$?
:
( exit $a ) && echo foo
私の答えは、質問を額面のまま受け入れ、「設定方法$?
(便利な表記法を使用)」の面白いクイズで解決することです。この場合、より深い意味、機能、または文脈(何も提供されていないため)を見つけようとしません。また、ソリューションの効果、効率、または有用性を判断することはありません。時々私は答えたときに「…しかしそうしないでください…」と言い、次に「代わりにこれをしなさい…」と言います。この場合、質問を簡単な好奇心クイズとして解釈することを選択しました。
これで、質問にさらに背景情報が追加されました。
サブシェル分岐の問題についての私の見解は、GNUなどのスクリプトがconfigure
実行できることです。いつも、非常に厳しい(長期実行)ループで実行されない限り、それほど遅くはありません。
parallel
私はGNUソフトウェアを頻繁に使用していないので、GNUでGNUを使用することについてあまり話すことはできません。
答え3
代替(より速いかもしれませんが、よりエレガントではありません):
test "$a" -eq 0 && echo foo
これは実行されますecho
が終了値をに設定しないので、これは$a
通常の解決策です。
答え4
仮定を確認してみましょう。
true && echo foo
fooを印刷します。 AND演算子の左側の関連性&&
により短絡論理ANDが続くため、一番左のコマンドが正常終了状態0(常に対応する)を返す場合は、その演算子の一番右のコマンドです。実行されます。&&
||
true
false && echo foo
fooは上記のものとは逆に印刷されません。bash -c "exit $a" && echo foo
$a
fooは本質的に誤った$a
制御仮定に従って印刷されます&&
。&&
AND論理なので、成功または失敗の2つの状態のみを認識します。ここで、失敗はゼロより大きい終了状態です。したがって、exit 1
andexit 2
and -はexit 3
;とは何の関係もありません。&&
失敗は値に関係なく失敗なので$a
実行echo foo
されません。
だから答えはいいえ、もうエレガントな方法はありませんそれにもかかわらず、間違った仮定の下で動作するタスクを実行します。しかし、コマンドで終了状態を設定することが目的であれば、Kusalalanandaの回答で提案されているサブシェルを使用するだけで十分です。個人的には、私はbash -c
サブシェルが別のプロセスではなくサブプロセス/フォークプロセスとして実装できることを除いて、部分的なものと変わらないと思います。ユーザーは$?
変数で設定しないでください。変数は、コマンドの成功または失敗を渡すために使用されます。
$a
しばらく焦点を変えてみましょう。なぜ設定して自分で確認できるのですか$?
?属さない値、つまりに値を配置することは意味がありません。私は「優雅さ」(それが何を意味するか)から「論理」と「仕事」に焦点を合わせることを提案します。echo foo
$a
$a
$?
さあ、ゲームをしましょう。それからインスピレーションを得るイルカチュウの答え。ただし、このアプローチでは、エコー条件付き実行を強制する必要はありません。指定された変数が成功を示す場合にのみエコーされ、return
実行を防ぎます。
$ thing(){ [ "${1-0}" -eq 0 ] || return "$1" ; echo "foo"; }
$ thing
foo
$ thing 0
foo
$ thing 1
$ echo $?
1
$ thing 2
$ echo $?
2
はっきりしないのは、できることだthing $a