그래서 나는 이것을 가지고 있습니다 :
(
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이 아닌 종료 상태(또는 모든 명령이 성공적으로 종료된 경우 0)를 갖는 가장 오른쪽 명령의 종료 상태가 되도록 합니다. 귀하의 경우 가지고 있는 유일한 파이프는 echo
+ jq
파이프이며 echo
실패할 가능성이 없으므로 해당 pipefail
옵션이 중복됩니다.
errexit
( ) 셸 옵션을 사용 set -e
하면 0이 아닌 종료 상태를 반환하는 첫 번째 명령에서 셸이 종료됩니다.~하지 않는 한이 명령은 코드에 있는 것과 같은 AND-OR 목록의 일부입니다.
!!! json parse error: 'xxxx'
코드 출력을 트리거 하는 유일한 방법은 if
쉘이 쓸 수 없는 경우 0이 아닌 종료 상태를 반환하는 복합 명령을 사용하는 것입니다 $file_path
.
개인적으로 나는 이 두 가지 쉘 옵션이 절대적으로 필요한 상황이 아니라면 피하고 싶습니다(내 쉘 스크립트에서는 이러한 상황 중 하나를 본 적이 없습니다).
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
발생 시 0이 아닌 종료 상태가 반환되지만(보통과 같이) 최종 표현식에서 빈 결과가 생성되면 , null
또는 도 반환됩니다 false
.
답변2
왜 그 메시지를 보길 기대하는지 정말 이해가 안 돼요. 명령 그룹의 종료 코드를 테스트하고 있습니다. 이는 그룹의 마지막 명령의 종료 코드를 테스트하고 있음을 의미합니다. 귀하의 경우 마지막 명령은 if
또는 if
true인 경우 다음과 같습니다 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
$
이것이 스크립트에 들어가는 내용입니다.