eとoを設定すると、シェルスクリプトが正しく実行されません。

eとoを設定すると、シェルスクリプトが正しく実行されません。

以下のコードでeとoがサンプリング時間を設定した場合、最後の行が実行されないのはなぜですか?

set -x
set -e
set -o pipefail

add=$(echo 'x' |grep '1x' | wc -l)
echo $add
echo '1'

ベストアンサー1

単一文字オプションを混在させるのではなく、-o optionすべての項目に長いオプション名を使用する方が明確です。

set -o xtrace -o errexit -o pipefail

where -o xtraceis -x, -o errexitis -e( pipefail, kshでは、他のほとんどのシェルで見つかり、まもなく標準になり、ほとんどのシェルには対応する単一文字がありません)

errexitつまり、未処理のコマンドが失敗した場合、スクリプトは終了します。pipefailつまり、パイプラインのコンポーネントのいずれかが失敗すると、パイプライン全体が失敗したと見なされます(そうでない場合は、最も右側のコンポーネントのみが考慮されます)。

したがって、echo 'x' |grep '1x' | wc -lこれら3つのコマンド(echo、、grepおよび)wcのいずれかが失敗すると、パイプラインは失敗します。

ここでは、出力に含まれる行がgrep見つからないため、失敗が報告されます。これは、同じ失敗したシャットダウン状態で実行されているサブシェルを終了するためです。結果の割り当ても失敗し、スクリプトを実行するシェルは終了します。1xechoerrexit$(...)var=$(...)

grep | wc -lこのように書くのがより良いことに注意してくださいgrep -c

効果を避けるには、errexitエラーを処理するだけです。

それは次のとおりです。

var=$(echo x | grep -c 1x || : no match should not be a fatal error)

|| another commandパイプラインの後、失敗はシェルによって手動で処理されると見なされるため、これにはerrexit適用されません。ここでは、コマンドは:何も正常に実行しません(true何もしない引数を許可することを除く)。

処理中のパイプラインエラーです。エラーを個別に処理することもできますgrep

var=$(
  echo x | {
    grep 1x || : no match should not be a fatal error
  } | wc -l
) 

スクリプトが失敗echoまたはwc終了することを許可します(ここにはスクリプトを実行するための追加のサブシェルが含まれますgrep || :)。

または、割り当て失敗を処理します。

var=$(echo x | grep -c 1x) || : no match should not be a fatal error

サブシェル内で無効にするかどうかは、シェルerrexitとそのバージョンによって異なります。たとえば、一部のシェルは出力xし、他のシェルは空の行を出力しますsh -ec 'v=$(false; echo x) || true; echo "$v"'

errexit(別名set -e)は非常に脆弱な機能です。最も単純なスクリプト以外の目的で使用したり、代わりに手動エラー処理を実行したりすることはお勧めできません。他のプログラミング言語と同様に、スクリプト内のすべてのコマンドラインが失敗した場合に何が起こるのかを諦めてください。

おすすめ記事