Saritha
Saritha

Reputation: 225

How to use regex to search the key and value and replace value with new value using jq

My json
{
    "license": " See license.md",
    "dependencies": {
        "@gx/core": "0.279.0-b1-abc-1234-0716.4567",
        "@gx/api": "0.279.0-b1-abc-1234-0716.4567",
        "@gx/name": "0.279.0-b1-abc-1234-0716.4567"
    }
}

I want to replace "0.279.0-b1-abc-1234-0716.4567" with "0.279.0-b1-abc-1234-0716.9856" in all places.

        jq '.dependencies[].["@gx/core"] |= (if . == "0.279.0-b1-abc-1234-0716.4567" then "0.279.0-b1-abc-1234-0716.9856" else . end)' info.json
jq: error: syntax error, unexpected '[', expecting FORMAT or QQSTRING_START (Unix shell quoting issues?) at <top-level>, line 1:
    .dependencies[].["@gx/core"] |= (if . == "0.279.0-b1-abc-1234-0716.4567" then "0.279.0-b1-abc-1234-0716.9856" else . end)                
    jq: 1 compile error   

I am looking for something like this
   jq '.dependencies[].["@gx/[a-z]*"] |= (if . == "^(\d+\.){2}[0-9]+(-[a-zA-Z0-9]*){4}\.[0-9]*$" then "0.279.0-b1-abc-1234-0716.9856" else . end)' info.json 

Upvotes: 0

Views: 232

Answers (2)

peak
peak

Reputation: 116690

Using jq, there are many different approaches, with very different semantics, as can be seen from these solutions to the first problem (without regexes):

walk(if . == "0.279.0-b1-abc-1234-0716.4567" 
     then "0.279.0-b1-abc-1234-0716.9856" else . end)

A more focused approach:

 .dependencies |=
   map_values(if . == "0.279.0-b1-abc-1234-0716.4567" 
              then "0.279.0-b1-abc-1234-0716.9856" else . end)

regexes

The above approaches can all be used in the case of regex searches too, e.g. the last case would become:

.dependencies |= with_entries(
  if (.key | test("@gx/[a-z]*"))
      and (.value | test("^(\\d+\\.){2}[0-9]+(-[a-zA-Z0-9]*){4}\\.[0-9]*$"))
  then .value = "0.279.0-b1-abc-1234-0716.9856" else . end)

Note that the regex strings must be JSON strings, and hence the doubling of backslashes.

if without else

If you have a sufficiently recent version of jq, those dangling occurrences of "else ." can be dropped.

Upvotes: 1

Dmitry
Dmitry

Reputation: 1293

if you up to considering a non-jq solution, let me offer here one based on a walk-path unix utility jtc:

bash $ <file.json jtc -w'[dependencies]<0\.279\.0\-b1\-abc\-1234\-0716\.4567>R:' -u'"0.279.0-b1-abc-1234-0716.9856"'
{
   "dependencies": {
      "@gx/api": "0.279.0-b1-abc-1234-0716.9856",
      "@gx/core": "0.279.0-b1-abc-1234-0716.9856",
      "@gx/name": "0.279.0-b1-abc-1234-0716.9856"
   },
   "license": " See license.md"
}
bash $ 

walk-path (-w):

  • [dependencies] addresses (from root) the given record
  • <...>R: - a search lexeme, finds using RE (suffix R) all (quantifier :) entries matching the given reg.expression.

-u will update (replace) all found matches.

-- or --

using your REs, matching both labels and values:

bash $ <file.json jtc -w'[dependencies]<@gx/[a-z]*>L:<^(\d+\.){2}[0-9]+(-[a-zA-Z0-9]*){4}\.[0-9]*$>R' -u'"0.279.0-b1-abc-1234-0716.9856"'
  • same result

PS> Disclosure: I'm the creator of the jtc tool

Upvotes: 1

Related Questions