简体   繁体   English

如何使用sed编辑json中的值

[英]How to edit value in json using sed

I have the following json file: 我有以下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"
        }

I am trying to change a particular parameter in value for key "JAVA_OPTS". 我试图更改键“ JAVA_OPTS”的值中的特定参数。 This is a part of Jenkins job, 这是詹金斯工作的一部分,

This is what I am trying to achieve, is to be able to change the value for parameter ${Config_Label} -Dspring.cloud.config.label=${Config_Label} 这是我想要实现的,是能够更改参数$ {Config_Label} -Dspring.cloud.config.label=${Config_Label}

And I have tried this solution which does not seem to work: 我尝试了这种似乎无效的解决方案:

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

But the syntax doesn't work and the Jenkins job fails with error 但是语法不起作用,Jenkins作业失败并显示错误

unexpected EOF while looking for matching `"' 寻找匹配的“”时出现意外的EOF

Hoping someone could correct me here. 希望有人可以在这里纠正我。 Thank you. 谢谢。

When modifying objects in jq, all it takes really is: 在jq中修改对象时,实际上只需要执行以下操作:

  1. Find the object you want to update 查找您要更新的对象

     # the environment object with the name "JAVA_OPTS" .environment[] | select(.name == "JAVA_OPTS") 
  2. Assign a new value to the property you want updated 为要更新的属性分配一个新值

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

At this point, it's just a question of, updating a string to replace with something else. 此时,只是一个问题,更新字符串以替换为其他字符串。 You can use a regular expression to do the replacement or any other replacement approach you'd like: 您可以使用正则表达式进行替换或您想要的任何其他替换方法:

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

Putting that all together: 放在一起:

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

Use the ' to enclose the sed script, in order to avoid escaping " . Your goal is to search for JAVA_OPTS , and then modify the string in the line after. 为了避免转义" ,请使用'包围sed脚本。您的目标是搜索JAVA_OPTS ,然后在之后的行中修改字符串。

I always have this super tutorial open aside in order to help: Sed - An Introduction and Tutorial by Bruce Barnett 我总是将这个超级教程放在一边以帮助: Sed-Bruce Barnett的简介和教程

N : this sed command reads the next line in the file and happends it to the pattern buffer. N :此sed命令读取文件中的下一行并将其出现在模式缓冲区中。

The example below is doing the trick but this is going to break easily when the json data vary; 下面的示例正在解决这个问题,但是当json数据变化时,这很容易打破。 it is recommended to use jq as @Iniam suggested. 建议使用@Iniam建议的jq

If you still want to have something working for the example in your question, give a try to this: 如果您仍然想解决问题中的示例,请尝试以下操作:

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

Same version on several lines: 在几行上使用相同的版本:

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

You could also do this with a simple Node script as well. 您也可以使用简单的Node脚本执行此操作。 If the shell environment variable is, say VERSION, you could use the following script for this replacement, as well as other possible manipulations of the file for the build process you might be running: 如果shell环境变量为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');
});

You can then run it like: 然后,您可以像这样运行它:

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

If the file contains Dspring.cloud.config.label only once 如果文件仅包含Dspring.cloud.config.label

You can directly use this: 您可以直接使用:

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

if you want to commit this change into your put -i after sed 如果您想在sed之后将此更改提交到put -i中

but if Dspring.cloud.config.label string comes multiple times please share more details of file. 但是,如果Dspring.cloud.config.label字符串多次出现,请共享文件的更多详细信息。

在此处输入图片说明

Since 以来

Dspring.cloud.config.label Dspring.cloud.config.label

was occurring only once in the json file, I have made use of sed function as mentioned by one of the users (Mohit Rathore). 在json文件中仅发生一次,我已经使用了其中一位用户(Mohit Rathore)提到的sed函数。 This may not be an exceptional solution, but it was simple and it worked in this use case. 这可能不是一个例外的解决方案,但它很简单并且可以在此用例中使用。

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

Thank you. 谢谢。

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

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