だから私はこれを持っています:
(
set -eo pipefail;
{
set -eo pipefail;
file_path="$(echo "$i" | jq -r '.file_path')"
if [[ -n "$file_path" ]]; then
echo "$i" > "$file_path";
fi
} || {
# never seems to reach here
echo "!!! json parse error: 'xxxx'";
}
)
私の端末では、次のようなものが欲しい。
!!! json parse error: 'xxxx'
jq
ところで、端末でこのようなエラーが発生し続けます。
parse error: Invalid numeric literal at line 2, column 0
私にとって一般的に動作する「catchブロック」がここで動作しない理由はわかりません。
答え1
のシェルpipefail
オプションは、bash
パイプの終了状態がゼロ以外の終了状態(またはすべてのコマンドが正常に終了した場合は0)を持つ最も右側のコマンドの終了状態になるようにします。あなたの場合、唯一のパイプはecho
+jq
パイプであり、echo
失敗する可能性がないため、そのpipefail
オプションは重複します。
errexit
()シェルオプションを使用するset -e
と、ゼロ以外の終了ステータスを返す最初のコマンドでシェルが終了します。〜しない限りこのコマンドは、コード内のものと同じAND-ORリストの一部です。
!!! json parse error: 'xxxx'
コード出力をトリガーする唯一の方法は、シェルが書き込めif
ない場合にゼロ以外の終了状態を返す複合コマンドを使用することです$file_path
。
個人的に、私はこれらの2つのシェルオプションが絶対に必要な状況でなければ避けたいと思います(私のシェルスクリプトではこれらの状況の1つを見たことがありません)。
jq
解析でnull以外の値が生成された場合は、JSONドキュメントをファイル(の出力から提供)に書き込み、解析に失敗した場合はエラーメッセージを出力したいようです。
おそらく構文解析がうまくいったことを確認する最も簡単な方法は、ステートメントjq
で直接終了状態を使用することです。if
ここでは、エラー出力をさらにキャプチャしてjq
独自のエラー報告に使用します。
if filepath=$( jq -r '.file_path' <<<"$json_document" 2>&1 )
then
# Parsing went ok.
if [ -n "$filepath" ]; then
# "$filepath" is non-empty.
printf '%s\n' "$json_document" >"$filepath"
fi
else
# Parsing failed.
printf 'ERROR: "%s"\n' "$filepath" >&2
fi
jq
しかし、正直に言うと、まったく介入せずに独自のエラー報告を実行することでコードを簡素化しました。
if filepath=$( jq -r '.file_path' <<<"$json_document" ) && [ -n "$filepath" ]
then
# Parsing went ok, and "$filepath" is non-empty.
printf '%s\n' "$json_document" >"$filepath"
fi
またはjq
、値が空であると仮定すると、テストは削除されます-n
。
if filepath=$( jq -r -e '.file_path' <<<"$json_document" )
then
# Parsing went ok, and "$filepath" is non-empty (and not null or false).
printf '%s\n' "$json_document" >"$filepath"
fi
の場合、-e
エラーjq
が発生したときにゼロ以外の終了状態が返されますが(通常のように)、最終式で空の結果が生成された場合、またはnull
返されますfalse
。
答え2
なぜそのメッセージを見たいと思うのか、本当に理解できません。コマンドグループの終了コードをテストしています。これは、グループの最後のコマンドの終了コードをテストしていることを意味します。あなたの場合、最後のコマンドはif
trueif
の場合は次のようになりますecho
。
if [[ -n "$file_path" ]]; then
echo is n
fi
これが最後のコマンド実行なのでそれ|| echo "!!! json parse error: 'xxxx'"
はテスト中のオブジェクトであり、両方が実行されif
てecho
trueを返すため、「catchブロック」を入力しません。
オプションのため、これを行う場合はpipefail
パイプではないため、機能しません。
$ { false | true; } || echo FAILED
$ set -o pipefail
$ { false | true; } || echo FAILED
FAILED
ただし、パイプの後ろに失敗することなく別のコマンドを追加すると、次のようになります。
$ { false | true; true;} || echo FAILED
$
これがスクリプトに入る内容です。