サブシェルとifブロックの違い

サブシェルとifブロックの違い

違いは何ですか?

set -e;
./create-git-tag.sh || {
   echo 'Could not create git tag.'
   exit 1;
}

そして

set -e;
if ! ./create-git-tag.sh; then 
    echo 'Could not create git tag.'
    exit 1;
fi

ifブロックがサブシェルを生成しないため、ifブロックが入力される前に終了するようです。機能的には同じように見えますが、動作に違いはありますか?

答え1

中かっこは{ }サブシェルを生成しませんが、かっこは次のことを行います。

大きな打撃(1)

リスト)

リストはサブシェル環境で実行されます。

{リスト;}

listは現在のシェル環境でのみ実行されます。

したがって、ifステートメントまたはフォームの両方が... || { }サブシェルを生成する可能性はありません。

サブシェル環境可能( )中括弧の代わりに括弧を使用して生成された場合。最初のコマンドが||ゼロ以外の状態を返す場合のみ(つまり。./create-git-tag.sh 失敗)

使用すると、set -eすべてのフォームは同じ動作を示します(テストコマンドが失敗すると、シェルはすぐに終了します)。しかし、後ろの括弧はサブシェルを生成します(この例では役に立たないようです)。

もしset -e いいえを使用してサブシェルを作成すると、サブシェルは( )終了しますが、呼び出しシェルは続行されます。以降のコマンドは引き続き実行されます。

すべての場合において、echo-exitコマンドチェーン(および括弧で囲まれた関連サブシェル)は、テストコマンドが失敗した場合にのみ入力されます。しかし、条件付きロジックを作成することの重要な点は、何かが失敗する可能性があります。これは質問の表現が理解できない部分です。

ifブロックはサブシェルを生成しないので、ifブロックが入力される前に終了するようです。

ブロックするとはい「入力」したら、テストコマンドを実行して次に実行するアクションを決定します。

個人的には、私はこのif文章が読みやすく、スクリプトで使用することを好むと思います。シェルを「インタラクティブに」使用すると、オペレーター&&||私はinを使用できます。if

答え2

私の理解はどちらの場合も同じで、exitスクリプトを実行しているシェルインスタンスがシャットダウンされるということです。

どちらのバージョンもサブシェルを生成しません。これを実証するために、次の実験を検討してください。

$ cat version1
#!/bin/bash

set -e

x=7

ls /tmp/does/not/exist &> /dev/null || {
    x=42
}

echo $x


$ ./version1
42
$ cat version2
#!/bin/bash

set -e

x=7

if [ ! ls /tmp/does/not/exist &> /dev/null ]; then
    x=42
fi

echo $x

$ ./version2
42

(次のバージョンに示すように)に{ }変更すると、サブシェルが作成されます。したがって、内部変更は呼び出しシェルには影響しません。version1()x( )x

$ cat version3
#!/bin/bash

set -e

x=7

ls /tmp/does/not/exist 2> /dev/null || (
    x=42
)

echo $x

$ ./version3
7

関連情報