繁体   English   中英

通过外壳脚本用jq更新json

[英]update json with jq through shell script

我创建了一个Shell脚本来使用jq创建和更新json文件。 创建json文件效果很好。 我有一个变量作为参数传递给jq命令

#!/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变量是正确的。 棚是正确的。 我认为我必须使用另一个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

使用jq-1.5更高版本支持的--argjson标志将参数$REPORT作为json参数--argjson

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

更改为

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

谢谢@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

不要手动生成JSON; jq做吧。 如果要添加到JSON的值需要正确引用,这很重要,如果仅在shell中执行字符串插值,则不会发生这种情况:

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

此外, jq可以生成日期和时间字符串; 也不需要运行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"

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM