我需要你的帮助来解决以下问题:我有一个JSON文件,看起来像这样:
{ "key1": "value1", "key2": "value2", "key3": "value3" }
如何通过bash脚本添加和删除新密钥(即"key4": "value4")?我还看到了在添加或删除新键之前在文件中最后一个键的末尾添加或删除逗号的问题。谢谢你
"key4": "value4"
lvmkulzt1#
您最好使用JSON CLI,例如**jq**:
jq
sudo apt-get install jq
brew install jq
示例,基于以下输入字符串-输出到stdout:
stdout
jsonStr='{ "key1": "value1", "key2": "value2", "key3": "value3" }'
jq 'del(.key3)' <<<"$jsonStr"
jq '. + { "key4": "value4" }' <<<"$jsonStr"
jq '.key1 = "new-value1"' <<<"$jsonStr"
一个更强大的替代方案,感谢Lars Kiesow:如果使用--arg传递新值,jq会负责正确转义该值:
--arg
jq '.key1 = $newVal' --arg newVal '3 " of rain' <<<"$jsonStr"
如果你想更新一个JSON文件(从概念上讲),以删除key 3为例:
# Create test file. echo '{ "key1": "value1", "key2": "value2", "key3": "value3" }' > test.json # Remove "key3" and write results back to test.json (recreate it with result). jq -c 'del(.key3)' test.json > tmp.$$.json && mv tmp.$$.json test.json
不能直接替换输入文件,因此结果将写入临时文件,成功后该临时文件将替换输入文件。请注意-c选项,它生成紧凑的JSON,而不是打印得漂亮的JSON。
-c
所有选项和命令参见https://jqlang.github.io/jq/manual/的手册。
xdnvmnnf2#
这不是每个人的答案,但是如果你已经在你的系统中安装了NodeJs,你可以用它来轻松地操作JSON。例如:
#!/usr/bin/env bash jsonFile=$1; node > out_${jsonFile} <<EOF //Read data var data = require('./${jsonFile}'); //Manipulate data delete data.key3 data.key4 = 'new value!'; //Output data console.log(JSON.stringify(data)); EOF
见鬼,如果你只需要做JSON操作,并且你有node(即:你不需要任何其他的bash功能)你可以直接使用node作为解释器来写一个脚本:
#! /usr/bin/env node var data = require('./'+ process.argv[2]); /*manipulate*/ console.log(JSON.stringify(data));
qyuhtwio3#
在Lenny的答案基础上,我们可以使用node的-p选项,它计算给定的脚本并将输出写入stdout。使用扩展运算符以便于修改,得到:
node -p "JSON.stringify({...require('./data.json'), key4: 'value4'}, null, 2)" > data.json
kwvwclae4#
要就地更改文件,请使用sponge命令
echo '{ "k": "old value" }' >f.json cat f.json | jq '.k = $v' --arg v 'new value' | sponge f.json
参见:jq issue Edit files in place #105JQ的替代方案:jaq
echo '{ "k": "old value" }' >f.json jaq -i '.k = $v' --arg v 'new value' f.json
...但是jaq的功能比jq少
jaq
lsmepo6l5#
下面是一个纯bash示例,包括“逗号问题”。
#!/bin/bash # This bash script just uses the sed command to # replace/insert a new key at/before/after an # existing key in a json file # The comma issue: # - replace: with/without, as previous entry # - before: always add # - after: add before, if there was none SED_CMD="/tmp/sed_cmd.tmp" JSFILE1="./data1.json" JSFILE2="./data2.json" JSFILE3="./data3.json" SEARCH_KEY="key3" # create json input file echo -e '{\n\t"key1": "value1",\n\t"key2": "value2",\n\t"key3": "value3"\n}' > $JSFILE1 echo -e "input:" cat $JSFILE1 # duplicate twice cp $JSFILE1 $JSFILE2 && cp $JSFILE1 $JSFILE3 # find the SEARCH_KEY and store the complete line to SEARCH_LINE SEARCH_LINE=`cat data.json | grep $SEARCH_KEY` echo "SEARCH_LINE=>$SEARCH_LINE<" # replace SEARCH_LINE IS_COMMA=`echo $SEARCH_LINE | grep ","` [ -z "$IS_COMMA" ] && \ echo "s+$SEARCH_LINE+\t\"keyNew\": \"New\"+g" > $SED_CMD || \ echo "s+$SEARCH_LINE+\t\"keyNew\": \"New\",+g" > $SED_CMD sed -i -f $SED_CMD $JSFILE1 echo -e "replace:" cat $JSFILE1 # insert before SEARCH_LINE echo "s+$SEARCH_LINE+\t\"keyNew\": \"New\",\n$SEARCH_LINE+g" > $SED_CMD sed -i -f $SED_CMD $JSFILE2 echo -e "before:" cat $JSFILE2 # insert after SEARCH_LINE IS_COMMA=`echo $SEARCH_LINE | grep ","` [ -z "$IS_COMMA" ] && \ echo "s+$SEARCH_LINE+$SEARCH_LINE,\n\t\"keyNew\": \"New\"+g" > $SED_CMD || \ echo "s+$SEARCH_LINE+$SEARCH_LINE\n\t\"keyNew\": \"New\",+g" > $SED_CMD sed -i -f $SED_CMD $JSFILE3 echo -e "after:" cat $JSFILE3 exit 0
jjjwad0x6#
使用专用的JSON工具,如xidel,比使用纯Bash函数更好。
xidel -s '{"a":1,"b":2,"c":3}' -e '($json).d:=4' # dot notation xidel -s '{"a":1,"b":2,"c":3}' -e '{|$json,{"d":4}|}' # JSONiq (deprecated) xidel -s '{"a":1,"b":2,"c":3}' -e 'map:put($json,"d",4)' # XQuery xidel -s '{"a":1,"b":2,"c":3}' -e 'map:merge(($json,{"d":4}))' # XQuery { "a": 1, "b": 2, "c": 3, "d": 4 }
"c":3
xidel -s '{"a":1,"b":2,"c":3}' --xmlns:jnlib="http://jsoniq.org/function-library" -e 'jnlib:remove-keys($json,"c")' # JSONiq (deprecated) xidel -s '{"a":1,"b":2,"c":3}' -e 'map:remove($json,"c")' # XQuery { "a": 1, "b": 2 }
"c"
4
xidel -s '{"a":1,"b":2,"c":3}' -e '($json).c:=4' xidel -s '{"a":1,"b":2,"c":3}' -e 'map:put($json,"c",4)' xidel -s '{"a":1,"b":2,"c":3}' -e 'map:merge(($json,{"c":4}),{"duplicates":"use-last"})' { "a": 1, "b": 2, "c": 4 }
6条答案
按热度按时间lvmkulzt1#
您最好使用JSON CLI,例如**
jq
**:sudo apt-get install jq
brew install jq
示例,基于以下输入字符串-输出到
stdout
:删除key 3:
添加属性key 4,属性值为value 4:
将现有属性key 1的值修改为new-value 1:
一个更强大的替代方案,感谢Lars Kiesow:
如果使用
--arg
传递新值,jq
会负责正确转义该值:如果你想更新一个JSON文件(从概念上讲),以删除key 3为例:
不能直接替换输入文件,因此结果将写入临时文件,成功后该临时文件将替换输入文件。
请注意
-c
选项,它生成紧凑的JSON,而不是打印得漂亮的JSON。所有选项和命令参见https://jqlang.github.io/jq/manual/的手册。
xdnvmnnf2#
这不是每个人的答案,但是如果你已经在你的系统中安装了NodeJs,你可以用它来轻松地操作JSON。
例如:
见鬼,如果你只需要做JSON操作,并且你有node(即:你不需要任何其他的bash功能)你可以直接使用node作为解释器来写一个脚本:
qyuhtwio3#
在Lenny的答案基础上,我们可以使用node的-p选项,它计算给定的脚本并将输出写入
stdout
。使用扩展运算符以便于修改,得到:
kwvwclae4#
要就地更改文件,请使用sponge命令
参见:jq issue Edit files in place #105
JQ的替代方案:jaq
...但是
jaq
的功能比jq
少lsmepo6l5#
下面是一个纯bash示例,包括“逗号问题”。
jjjwad0x6#
"key4": "value4"
)?*使用专用的JSON工具,如xidel,比使用纯Bash函数更好。
添加新的属性值对
删除属性值对
"c":3
将
"c"
属性值改为4