2017-10-09 2 views
0

JSON 필드가 비어 있거나 비어 있지 않은 오류 메시지에 따라 오류를 감지하려고합니다. jq를 사용하여 멤버를 잘라내지만 "bash"에서 평가할 때 큰 어려움이 있습니다.bash JSON with jq - 빈 JSON 멤버를 확인하는 방법은 무엇입니까?

나는 (~ $를 내 CLI 프롬프트가 있습니다)를 errmsg를 멤버를 가지고 내 변수 $ 입력에 의해 참조되는 JSON 파일을 가지고 있지만 빈 문자열로 :

~$ echo $(jq "." $input) 
{ "projectCode": "145", "fullCode": "1", "errMsg": "" } 

가에 errmsg를 필드를 검색

~$ err=$(jq ".errMsg" $input) 
~$ echo $err 
"" 

문제 : 그 변수를 테스트하는 것은 불가능 보인다

~$ if [ $err = "" ]; then echo EMPTY; else echo CONTENT; fi 
CONTENT 
이 경우 제대로 빈 문자열을 산출

""라고 표시된 $ err로 비 었음을 예상했습니다. 다른 방법으로 확인 :

~$ if [ $err != "" ]; then echo EMPTY; else echo CONTENT; fi 
EMPTY 

echo $ err yield ""이더라도 $ err은 분명히 ""가 아닙니다. 어떻게 그럴 수 있습니까? 어떤 bash 기능이 여기에없는가요? 나는 그것이 발견 추측

~$ if [ "$err" != "" ]; then echo EMPTY; else echo CONTENT; fi 
bash: syntax error near unexpected token `then' 

:

~$ echo $(jq "." $input) 
{ "projectCode": "145", "fullCode": "1", "errMsg": "not empty" } 
~$ echo $err 
"not empty" 

~$ if [ $err != "" ]; then echo EMPTY; else echo CONTENT; fi 
bash: syntax error near unexpected token `then' 

가 좋아, 다음과 같이 마스킹 :

은 어쨌든합니다 ($ 입력 내용을 변경 한 후) 비어 있지 않은 JSON과 그 시도 할 수 있습니다 두 번째 토큰은 "not"다음에 나옵니다. 그것은 또한 비어에 errmsg 회원 작동

~$ val=$(sed "s/^\(\"\)\(.*\)\1\$/\2/g" <<<"$err" | sed -e 's/\s.*$//') 
~$ if [ "$val" = "" ]; then echo "NO ERROR"; else echo "ERROR"; fi 
NO ERROR 

: 많은 연구 후 나는 작동하는 것 같다이 진정으로 읽을 솔루션을 찾을 수 있습니다. 제발, 간단하고 우아한 해결책이 있어야합니다.

+0

'[$ err = ""]'는 안전하지 않은 배쉬 코드입니다. 'jq'와는 아무런 관련이 없습니다. 'err'이 비어 있으면 유효한 문법이 아닌'[= ""]'을 실행합니다. '[ "$ err"= ""]'이 필요합니다. –

+0

'''if [ "$ err"! = ""]; echo EMPTY; else echo CONTENT; fi''' - 정말로, 정말로 *는 문법 오류가 아닙니다. ('! ='는 논리 오류가 있음을 의미합니다). https://ideone.com/CblHNK –

+0

에서 제대로 실행되는지 확인하십시오. 다른 사람들이 복사하여 붙여 넣기하여 특정 버그를 재현 할 수있는 코드 형태로 [mcve]를 제공 할 수 있다면 (이상적으로 테스트 한 재생기 이데온 또는 다른 편견적인 제 3 자 샌드 박스에서 작업하기 위해), 나는 그것을보고 매우 흥미가있을 것입니다. –

답변

1

위로부터이 부분을 살펴보고 무슨 일이 일어나는지 이해해보십시오.

~$ err=$(jq ".errMsg" $input) 
~$ echo $err 
"" 

이 출력

err (이것은 또한 이전과 이후 "" 일부 공간을 가질 수있다) ""를 포함 함을 나타낸다. 빈 문자열과 같은 것은 아닙니다. 문자 그대로 두 개의 큰 따옴표 문자입니다.
~$ if [ $err = "" ]; then echo EMPTY; else echo CONTENT; fi 
CONTENT 

나는 $로 EMPTY는 "단지"가 나타났다 잘못 excpected.

앞서 언급했듯이 $err은 비어 있지 않으며 두 개의 큰 따옴표를 포함합니다. 한편, Bash 문 [ ... = "" ]에서 ""은 실제로 빈 값을 의미합니다.$err의 값이 비어 있거나 공백이 포함 된 경우 (당신이 IFS을 사용자 정의하지 않은 가정) 경우에 구문 오류가 발생합니다 때문에

배쉬 문 [ $err = "" ]는 , 문제가있다.

큰 따옴표로 $err 묶이 명령문을 작성하는 올바른 방법 :

err=$(jq ".errMsg" "$input") 
:

이 같은 첫 번째 명령에 $input 변수에 간다
if [ "$err" = "" ]; then echo EMPTY; else echo CONTENT; fi 

, 그것이로 작성해야한다


개체에 .errMsg 값이 비어 있는지 확인하려면 값을 두 개 이상 지정해야합니다.

옵션 1 : 값이 ""인지 확인하십시오.

if [ "$err" = '""' ]; then echo EMPTY; else echo CONTENT; fi 

옵션 2 : 그것은 문자열 값 주위를 둘러싸는 큰 따옴표를 포함하지 않는, 그래서 원시 모드에서 jq 출력을합니다. err의 값이 실제 값이 될 수 있도록

err=$(jq -r ".errMsg" "$input") 
if [ "$err" = "" ]; then echo EMPTY; else echo CONTENT; fi 

나는,이 후자의 옵션을 사용하는 것이 좋습니다. 둘러싼 큰 따옴표는 당신의 목적에 맞는 단순한 것 같습니다. 다음과 같이

+0

감사합니다. jq -r은 필요한 것입니다. 간결하고 간결한 작품. 더 이상 sed는 필요하지 않습니다. – onouv

+0

@onouv이 질문에 대한 답변을 주셨을 경우에는 받아 들일 수 있습니다. – janos

1

당신은 기본 bash는 연관 배열로 전체 구조를 읽을 수 있습니다 거기에서

declare -A data=() 
while IFS=$'\t' read -r key value; do 
    data[$key]=$value 
done < <(jq -r 'to_entries[] | [.key, .value] | @tsv' "$input") 

, 당신은 몇 가지 옵션이 있습니다 : 당신은 개별적으로 항목을 확인할 수 있습니다 ...

[[ ${data[errMsg]} ]] || echo "ERROR: errMsg is not set!" 

합니다. .. 또는 모두 반복 할 수 있습니다 :

for key in "${!data[@]}"; do 
    [[ ${data[$key]} ]] || echo "ERROR: ${key} is not set!" 
done 
관련 문제