如何使用sed编辑json中的值

时间:2018-12-20 16:16:48

标签: json bash sed jq

我有以下json文件:

"environment": [
        {
          "name": "DD_AGENT_HOST",
          "value": "somevalue.com"
        },
        {
          "name": "DD_AGENT_PORT",
          "value": "1234"
        },
        {
          "name": "DD_TRACE_SPAN_TAGS",
          "value": "env:test"
        },
        {
          "name": "JAVA_OPTS",
          "value": "-javaagent:/dd-java-agent/dd-java-agent.jar -Xms512m -Xmx2548m -XX:MaxPermSize=512m -Dspring.profiles.active=testapp -Dspring.cloud.config.label=<some value> -Duser.timezone=America/New_York"
        }

我正在尝试更改键“ JAVA_OPTS”的值中的特定参数。 这是詹金斯工作的一部分,

这是我要实现的目标,是能够更改参数$ {Config_Label} -Dspring.cloud.config.label=${Config_Label}

的值。

我尝试了这种似乎无效的解决方案:

sed -i "/value/c\   \"value\" : \"-javaagent:/dd-java-agent/dd-java-agent.jar -Xms512m -Xmx2548m -XX:MaxPermSize=512m -Dspring.profiles.active=testapp -Dencrypt.key=bjb4343knwdc -Dspring.cloud.config.label=${Config_Label} -Duser.timezone=America/New_York"\"," file.json

但是语法不起作用,Jenkins作业失败并显示错误

  

寻找匹配的“”“时出现意外的EOF

希望有人可以在这里纠正我。 谢谢。

5 个答案:

答案 0 :(得分:2)

在jq中修改对象时,实际上只需要:

  1. 找到要更新的对象

    # the environment object with the name "JAVA_OPTS"
    .environment[] | select(.name == "JAVA_OPTS")
    
  2. 为要更新的属性分配新值

    # update the value property using (= or |=)
    .environment[] | select(.name == "JAVA_OPTS").value = ...
    

这只是一个问题,更新一个字符串以替换为其他字符串。您可以使用正则表达式进行替换或您想要的任何其他替换方法:

sub("(?<k>-Dspring\\.cloud\\.config\\.label)=<some value>"; "\(.k)=${Config_Label}")

将它们放在一起:

.environment[] | select(.name == "JAVA_OPTS").value
    |= sub("(?<k>-Dspring\\.cloud\\.config\\.label)=<some value>"; "\(.k)=${Config_Label}")

答案 1 :(得分:1)

使用'来封装sed脚本,以避免逃脱"。 您的目标是搜索JAVA_OPTS,然后在后面的行中修改字符串。

我总是将本次超级教程放在一边以提供帮助:Sed - An Introduction and Tutorial by Bruce Barnett

N:此sed命令读取文件中的下一行并将其出现在模式缓冲区中。

下面的示例正在解决这个问题,但是当json数据变化时,这很容易打破。建议按照@Iniam的建议使用jq

如果您仍然想解决问题中的示例,请尝试以下操作:

sed -i '/"name"[[:blank:]]*:[[:blank:]]*"JAVA_OPTS"[[:blank:]]*,/ { N ; s/-Dspring.cloud.config.label=\(.*\) -Duser/-Dspring.cloud.config.label=${Config_Label} -Duser/ ; }' file.json

在几行上具有相同的版本:

sed -i '/"name"[[:blank:]]*:[[:blank:]]*"JAVA_OPTS"[[:blank:]]*,/ {
    N
    s/-Dspring.cloud.config.label=\(.*\) -Duser/-Dspring.cloud.config.label=${Config_Label} -Duser/
} ' file.json

答案 2 :(得分:1)

您也可以使用简单的Node脚本执行此操作。如果说外壳环境变量是VERSION,则可以使用以下脚本进行此替换,以及为可能正在运行的构建过程使用文件的其他可能操作:

#!/usr/bin/env node
// replace.js
const chunks = [];

process.stdin.resume();
process.stdin.setEncoding('utf8');

process.stdin.on('data', (chunk) => {
    chunks.push(chunk);
});

process.stdin.on('end', () => {
    const json = JSON.parse(chunks.join(''));

    // Process json.environment array
    json.environment = json.environment.map(obj => {
        if (obj.name == 'JAVA_OPTS') {
                obj.value = obj.value.replace(/(-Dspring.cloud.config.label=)([^\s]+)/, `$1${process.env.VERSION}`);
        }
        return obj;
    });

    process.stdout.write(JSON.stringify(json, null, 2));
    process.stdout.write('\n');
});

然后您可以像这样运行它:

$ VERSION=v6.7 ./replace.js < YOURFILE.json

答案 3 :(得分:1)

如果该文件仅包含一次 Dspring.cloud.config.label

您可以直接使用此:

 sed 's/Dspring.cloud.config.label=\S*/Dspring.cloud.config.label=${Config_Label}/g' json

如果您希望在sed之后将此更改提交到put -i中

但是如果 Dspring.cloud.config.label 字符串多次出现,请共享文件的更多详细信息。

enter image description here

答案 4 :(得分:0)

  

Dspring.cloud.config.label

在json文件中仅发生一次,我利用了其中一位用户(Mohit Rathore)提到的sed函数。 这可能不是一个例外的解决方案,但它很简单并且可以在此用例中使用。

sed -i "s/Dspring.cloud.config.label=\S*/Dspring.cloud.config.label=${Config_Label}/g" file.json 

谢谢。