2017-02-17 76 views
0

我創建了一個shell腳本來使用jq創建和更新json文件。創建json文件運行良好。我有一個變量作爲參數傳遞給jq命令使用jq通過shell腳本更新json

#!/bin/sh 
OPER=$1 
FILE_PATH=$2 
DATE_TIME=`date +%Y-%m-%d:%H:%M:%S` 
DATE=`date +%Y-%m-%d` 
CSV=$3 
STEP=$4 
STATUS=$5 
CODE=$6 
MESSAGE=$7 

if [ "$#" -eq 7 ]; then 
    if [ "$OPER" == "create" ]; then 
     # echo "FILE_PATH: $FILE_PATH - CSV: $CSV - STEP: $STEP - STATUS: $STATUS - CODE: $CODE - MESSAGE: $MESSAGE" 
     REPORT="{\"date\": \"$DATE\", \"csv\": \"$CSV\", \"messages\": [{ \"timestamp\": \"$DATE_TIME\", \"step\": \"$STEP\", \"status\": \"$STATUS\", \"code\": \"$CODE\", \"message\": \"$MESSAGE\" }] }" 
     echo ${REPORT} | jq . > $FILE_PATH 
    elif [ "$OPER" == "update" ]; then 
       echo "FILE_PATH: $FILE_PATH - CSV: $CSV - STEP: $STEP - STATUS: $STATUS - CODE: $CODE - MESSAGE: $MESSAGE" 
     REPORT="{\"timestamp\": \"$DATE_TIME\", \"step\": \"$STEP\", \"status\": \"$STATUS\", \"code\": \"$CODE\", \"message\": \"$MESSAGE\"}" 
     echo "REPORTTTTT: "$REPORT 
     REPORT="jq '.messages[.messages| length] |= . + $REPORT' $FILE_PATH" 
     #echo $REPORT 
     echo `jq '.messages[.messages| length] |= . + $REPORT' $FILE_PATH` > $FILE_PATH 
    else 
     echo "operation not recognized: $OPER" 
    fi 
else 
     echo "wrong parameters." 
fi 
jq . $FILE_PATH 

但是,要更新json文件,我得到一個錯誤。我的$ REPORT變量是正確的。 cotes是正確的。我想我必須使用另一個jq參數,而不是|= . +。我用純文本使用該命令,它工作。但是,當我動態創建REPORT變量時,會引發錯誤。

任何線索?感謝

REPORTTTTT: {"timestamp": "2017-02-17:12:11:11", "step": "2", "status": "OK", "code": "34", "message": "message 34 file.xml"} 
jq: error: syntax error, unexpected INVALID_CHARACTER, expecting $end (Unix shell quoting issues?) at <top-level>, line 1: 
'.messages[.messages| 
jq: 1 compile error 

jq: error: REPORT/0 is not defined at <top-level>, line 1: 
.messages[.messages| length] |= . + $REPORT          
jq: 1 compile error 

這裏是在命令行的示例>>

$ jq . file.json 
{ 
    "date": "2017-02-17", 
    "csv": "file.csv", 
    "messages": [ 
    { 
     "timestamp": "2017-02-17:12:31:21", 
     "step": "1", 
     "status": "OK", 
     "code": "33", 
     "message": "message 33" 
    } 
    ] 
} 
$ export REPORT="{\"timestamp\": \"2017-02-17:11:51:14\", \"step\": \"2\", \"status\": \"OK\", \"code\": \"34\", \"message\": \"message 34 file.xml\"}" 
$ echo $REPORT 
{"timestamp": "2017-02-17:11:51:14", "step": "2", "status": "OK", "code": "34", "message": "message 34 file.xml"} 
$ jq '.messages[.messages| length] |= . + $REPORT' file.json 
jq: error: REPORT/0 is not defined at <top-level>, line 1: 
.messages[.messages| length] |= . + $REPORT          
jq: 1 compile error 
+1

創建一個最簡單的例子,顯示哪個命令失敗?當前信息不可讀 – Inian

+1

https://stackoverflow.com/help/mcve – hek2mgl

回答

1

傳遞參數如$REPORT使用從jq-1.5起支持--argjson標誌一個json說法,

--argjson name JSON-text:  
This option passes a JSON-encoded value to the jq program as a predefined variable. 

Ch您的線路,

jq --argjson args "$REPORT" '.data.messages += [$args]' file 
0

Thanks @Inian。我改變了一點,但工作....這裏是解決方案。

if [ "$#" -eq 7 ]; then 
    if [ "$OPER" == "update" ]; then 
     echo "update Json" 
       echo "FILE_PATH: $FILE_PATH - CSV: $CSV - STEP: $STEP - STATUS: $STATUS - CODE: $CODE - MESSAGE: $MESSAGE" 
     REPORT="{\"timestamp\": \"$DATE_TIME\", \"step\": \"$STEP\", \"status\": \"$STATUS\", \"code\": \"$CODE\", \"message\": \"$MESSAGE\"}" 
     echo "REPORTTTTT: "$REPORT 
     echo `jq --argjson args "$REPORT" '.data.messages += [$args]' $FILE_PATH` > $FILE_PATH 
    else 
     echo "operation not recognized: $OPER" 
    fi 
else 
     echo "wrong parameters." 
fi 
+0

這不會在上面的答案中添加任何新內容。刪除它並標記我接受的答案以標記它已解決 – Inian

+0

爲什麼使用'jq'生成JSON *和*手動定義'REPORT'? – chepner

0

不要手工生成JSON;讓jq做到這一點。

$ foo='"hi" he said' 
$ json="{ \"text\": \"$foo\" }" 
$ echo "$json" 
{ "text": ""hi" he said" } # Wrong: should be { "text": "\"hi\" he said" } 

此外,jq可以生成日期和時間:如果需要適當引用您要添加到JSON的值,這將不會發生,如果你只是在shell執行字符串插值這一點很重要串;也不需要運行date(兩次)。

#!/bin/sh 

if [ $# -eq 7 ]; then 
    printf "Wrong number of parameters: %d\n" "$#" >&2 
    exit 1 
fi 

oper=$1 file_path=$2 

# Generate the new message using arguments 3-7 
new_message=$(
    jq -n --arg csv "$3" --arg step "$4" \ 
     --arg status "$5" --arg code "$6" \ 
     --arg message "$7" '{ 
    timestamp: now|strftime("%F:%T"), 
    csv: $csv, step: $step, status: $status, code: $code, message: $message}' 
) 

case $oper in 
    create) 
    jq -n --argjson new_msg "$new_message" --arg csv "$3" '{ 
     date: now|strftime("%F"), 
     csv: $csv, 
     messages: [ $new_msg ] 
    }' > "$file_path" 
    ;; 

    update) 
    jq --argjson new_msg "$new_message" \ 
     '.messages += [ $new_msg ]' \ 
     "$file_path" > "$file_path.tmp" && mv "$file_path.tmp" "$file_path" ;; 

    *) printf 'operation not recognized: %s\n' "$oper" >&2 
    exit 1 ;; 
esac 
jq '.' "$file_path"