||条件付き実行ブロックと括弧に関する問題

||条件付き実行ブロックと括弧に関する問題

だからこれは簡単なはずです。スクリプトの上部で条件をテストし、条件が失敗した場合はスクリプト全体を終了しようとし、終了時に2つのステートメントを実行したいと思います。 2番目のドアなしで単独でexit動作しますが、2番目のドアをどのように追加しても完全に終了することはできません。暗黙のグルーミング規則は、これらすべての項目が1行になければならないことです。私はスクリプトへのこの1行の変更が期待どおりに機能しないときにこれを見つけました。スクリプトは続きます。

まず、何かをお見せしましょう。する働く$USER 変数が "x" でない場合は、次の行が完全に終了するので問題ありません。ターミナルウィンドウにこの行を入力すると、そのターミナルウィンドウが閉じて(ユーザーIDが実際に「x」でない限り)、実際にはトップレベルのシャットダウンを実行するため、これが機能することがわかります。

[ $USER = 'x' ] || exit 1

だから私が望むように大丈夫です。しかし、終了する前にメッセージをエコーし​​たい場合は、エコーを追加しようとすると終了が発生しなくなったり、むしろ「別の方法」で動作するようです。 bash関数のコンテキストと同じことが起こります。次の行はいいえ端末を閉じます。迷惑ですね。

[ $USER = 'x' ] || (echo "Time to bail" ; exit 1)

セミコロンがエコーに食べられたかもしれないと思っていましたが、出口に当たらないようです。私はどのように知っていますか?上記のコードを変更してecho $?上記の「1」に入力した値が表示されます。もちろん、閉じたい端末ウィンドウで値を見るのに閉じません。

次のバリエーションは、echoと2番目のステートメントを実行する2番目の方法も示していますが、exitを使用すると同じ動作が再び発生します。

[ $USER = 'x' ] || (echo "Time to bail" && exit 1)

ここで誰かがこれを変にするだけでなく、合理的に見えるようにすることを願っています。

では、一行では不可能ですか?

(:)bash --versionGNU bash, version 4.3.30(1)-release

答え1

あなたが探しているのはこれです:

[ "$USER" = "x" ] || { echo "Time to bail"; exit 1; }

この{ list; }ステートメントは、現在のシェルコンテキストで指定されたリストのコマンドを実行します。シンボルとは異なり、サブシェルは作成されません( list )。カッコ間の呼び出しは、exit親シェル自体ではなく子シェルを終了します。


あなたの質問に含まれている1つ以上のif文の例は構文的に正確です。この動作を再現できません。行数は重要ではありません。 if ステートメントは本文でサブシェルを起動しません。


$USER注:変数が空の場合、構文が拡張されて効果がないため、条件の変数に二重引用符を追加しました[ = "x" ]。二重引用符を使用すると[ "" = "x" ]

答え2

ヒントをありがとう@mikeservに感謝します。答えは非常に簡単で、括弧が非常に特定の種類のグループ化を表すことを認識することが重要です。括弧はサブシェルを生成するため、いわゆる「トップレベル」出口が欠落しているようです。

完全な説明はここ、主な抜粋は次のとおりです。

中かっこの間にコマンドリストを配置するとサブシェル環境が作成されます...中かっこの間にコマンドリストを配置すると、そのリストは現在のシェルコンテキストで実行されます。

しかし、ここで少し不快なことは、2つが完全に交換可能ではないということです。中括弧は最後の中括弧の前にセミコロンが必要ですが、括弧はそうではありません。私が従う構文はセミコロンを削除し、「&&」形式を使用しようとします。

[ $USER == 'x' ] || {echo "ジュエリータイム"&&終了1;

全体として、括弧は中括弧よりも見やすく、中括弧には1行が1行のように見えないようにセミコロンが必要です。

関連情報