仅更改文件中的特定部分并跳过其他部分

时间:2014-07-11 22:43:19

标签: json file shell

我只想更改文件的某个部分,如下所示:

{
   "Section_A": {
    "ws/abc-Location01": 24, 
    "ws/abc-Location02": 67,
    "ws/abc-Location03:  101,
   },
   "Section_B": {
    "ws/abc-Location01": 33, 
    "ws/abc-Location02": 59,
    "ws/abc-Location03:  92,
   }
}

我想根据shell脚本中位置名称与数组的匹配,更改仅B节中字段2中的数值

例如,如果我的脚本中的数组中存在ws/abc-Location01,则不应更改其值,否则应将其值更改为file1.txt中第2个字段的值,其中第1个字段包含位置名称(如ws/abc-Location01

我不确定如何解决这个问题,因为每个部分都会出现一个给定的位置名称。那么如何告诉我的脚本忽略A部分,C部分等,只是改变B部分的值?

2 个答案:

答案 0 :(得分:0)

使用jq

# list all the keys in Section B into a bash array
keys_str=$(jq --raw-output '.["Section_B"] | keys | @sh' <test.json)
eval "keys_arr=( $keys_str )"

# determine which keys are not present in your other array
# assumes that the other array is associative for sanity
keys_to_change=( )
for key in "${keys_arr[@]}"; do
  [[ ${other_array[$key]} ]] || keys_to_change+=( "$key" )
done

for key in "${keys_to_change[@]}"; do
  # this is the inefficient way to do this, but it's much less code / easier
  # to show; in this case, we're changing everything listed to 0, since you
  # don't specify how you want to change them more precisely.
  jq --arg key "$key" \
    '.["Section_B"][$key] = 0' \
    <test.json >test.json.new \
    && mv test.json.new test.json
done

一般来说,语法识别工具是你最好的选择 - 就像人们提出有关XML的类似问题被告知要使用XMLStarlet或其他XPath引擎一样,使用正确的JSON解析器和生成器是进行编辑的正确方法。这可能需要安装额外的依赖项 - 但它确保您实际生成语法上有效的内容。

答案 1 :(得分:0)

假设您的文件是正确的JSON(它不是似乎在您的示例文件中是这种情况 - 但您在评论中确认了它),您最喜欢的脚本语言的几行应该是足够的。

就我自己而言,我使用了Python:

import sys
import json

data = json.load(sys.stdin)
data["Section_B"]["ws/abc-Location02"] = 9999
json.dump(data, sys.stdout,indent=True)

假设该文件存储为&#34; change.py&#34;

# Original data (proper JSON)
$ cat data.json 
{
   "Section_A": {
    "ws/abc-Location01": 24, 
    "ws/abc-Location02": 67,
    "ws/abc-Location03": 101
   },
   "Section_B": {
    "ws/abc-Location01": 33, 
    "ws/abc-Location02": 59,
    "ws/abc-Location03": 92
   }
}

# Pipe original data to our filter
$ cat data.json | python change.py 
{
 "Section_A": {
  "ws/abc-Location01": 24, 
  "ws/abc-Location02": 67, 
  "ws/abc-Location03": 101
 }, 
 "Section_B": {
  "ws/abc-Location01": 33, 
  "ws/abc-Location02": 9999, 
  "ws/abc-Location03": 92
 }
}

如果您想要一个仅限shell的解决方案,sed可能就足够了:

cat data.json | sed '/Section_B/,/}/{/Location02/s/:[^,]*/ 9999/}'

这显然更短;但也更脆弱...... 从好的方面来说,这将处理类似JSON的文件以及正确的JSON(假设在您的示例中格式化)。