我创建了一个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
以下是命令行&gt;&gt;
的示例$ 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
答案 0 :(得分:2)
使用从$REPORT
开始支持的--argjson
标记,将参数json
作为jq-1.5
参数传递,
--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
答案 1 :(得分:0)
谢谢@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
答案 2 :(得分:0)
不要手工生成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"