Search code examples
jsonregexbashjqinplace-editing

increment a numerical value in a json with jq


I have a json which looks like this:-

{
    "name": "abc",
    "version": "20.02.01",
    "tag": "24",
    "abc_version": "20.02",
    "registry": "registry.abc.com",
    "vendor": "greenplanet",
    "apps": [
      {
        "name": "abc-app",
        "version": "20.02.01-16",
        "volumes": [
          "/dev/log:/dev/log"
        ],
        "max_instances": "1"
      },
      {
        "name": "xyz-app",
        "version": "2.0.0-2",
        "volumes": [
          "/dev/log:/dev/log"
        ],
        "max_instances": "1"
      }      
    ]
}

based on a condition I need to increment the abc-app's or xyz-app's version. At present its at "20.02.01-16" for abc-app and I need to change it to "20.02.01-17". Also I need to increment the tag of the parent app which is "abc" to "25" I am able to increment the version with sed but that is not working for me:-

./jq -r ".apps" version.json | ./jq -r ".[] | .version" | grep -v '1.0.2' |sed -r 's/([0-9]+.[0-9]+.[0-9]+)(.*)([0-9]+)/echo "\1\2$((\3+1))"/e'

I need to increment all the above conditions in-place in json or maybe into a temporary file which I can move to original.

Thank you in advance.


Solution

  • First, let's define a helper function to perform the incrementation:

    # return a string
    def inc:
      (capture("(?<pre>.*)-(?<post>[0-9]+$)") | "\(.pre)-\( (.post|tonumber) + 1 )")
      // "\(tonumber+1)" ;
    

    The remainder of the solution can now be written in two lines, one for each value to be incremented:

    .tag |= inc
    | .apps |= map(if .name == "abc-app" then .version |= inc else . end)
    

    In-place editing

    You could use sponge, or a temporary file, or ... (see e.g. "How can "in-place" editing of a JSON file be accomplished?" on jq's FAQ).