Bash:状態を設定するエレガントな方法ですか? [閉鎖]

Bash:状態を設定するエレガントな方法ですか? [閉鎖]
  • true && echo foo印刷されますfoo
  • false && echo foo印刷されませんfoo
  • bash -c "exit $a" && echo foofooに従って印刷されます$a

最後のものを書くためのよりエレガントな方法はありますか?終了値を設定するためにシェルを起動する必要があるのはやや面倒です。私は次のことを考えています:

  • return $a && echo foo
  • exit $a && echo foo

ただし、return機能でのみ機能し、決して実行されませexitecho 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 foofooを印刷します。 AND演算子の左側の関連性&&により短絡論理ANDが続くため、一番左のコマンドが正常終了状態0(常に対応する)を返す場合は、その演算子の一番右のコマンドです。実行されます。&&||true

  • false && echo foofooは上記のものとは逆に印刷されません。

  • bash -c "exit $a" && echo foo$afooは本質的に誤った$a制御仮定に従って印刷されます&&&& AND論理なので、成功または失敗の2つの状態のみを認識します。ここで、失敗はゼロより大きい終了状態です。したがって、exit 1and exit 2and -は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

関連情報