You are not logged in.

#1 2018-08-24 13:29:00

tony5429
Member
Registered: 2006-03-28
Posts: 1,017

[SOLVED] Simpler Solution for jq Search-and-Replace?

I have the following contacts.json file:

[
  {
    "name": "John",
    "email": "john@hi.com"
  },
  {
    "name": "George",
    "email": "george@hi.com"
  },
  {
    "name": "Sally",
    "email": "sally@email.com"
  }
]

If I want to search for the entry with name $needle and switch its email address to $newemail, I can run the following script (with, as an example, $needle set to "John" and $newemail set to "hi@hi.com"). I'm wondering if there's a simpler way to do this, using just jq and standard linux commands...

needle="John"
newemail="hi@hi.com"
i=0
numentries=$(jq -r '.[].name' contacts.json | wc -l)
echo "[" >> temp.json
jq -r '.[].name' contacts.json | while read -r name ; do
  ((i++))
  if [ $name = $needle ] ;  then
    jq --arg needle "$needle" --arg newemail "$newemail" '.[] | select(.name == $needle) | .email = $newemail' contacts.json >> temp.json
  else
    jq --arg name "$name" '.[] | select(.name == $name)' contacts.json >> temp.json
  fi
  if [ $i -lt $numentries ] ; then
    echo "," >> temp.json
  fi
done
echo "]" >> temp.json
jq '.' temp.json > contacts.json
rm temp.json

I'd really like a one-line solution, but condensing the above into a single line is very ugly...

needle="John" ; newemail="hi@hi.com" ; i=0 ; numentries=$(jq -r '.[].name' contacts.json | wc -l) ; echo "[" >> temp.json ; jq -r '.[].name' contacts.json | while read -r name ; do ((i++)) ; if [ $name = $needle ] ;  then jq --arg needle "$needle" --arg newemail "$newemail" '.[] | select(.name == $needle) | .email = $newemail' contacts.json >> temp.json ; else jq --arg name "$name" '.[] | select(.name == $name)' contacts.json >> temp.json ; fi ; if [ $i -lt $numentries ] ; then echo "," >> temp.json ; fi ; done ; echo "]" >> temp.json ; jq '.' temp.json > contacts.json ; rm temp.json

Last edited by tony5429 (2018-08-24 14:54:28)

Offline

#2 2018-08-24 14:38:01

progandy
Member
Registered: 2012-05-17
Posts: 5,184

Re: [SOLVED] Simpler Solution for jq Search-and-Replace?

I am no expert with jq, but this seems to work:

jq -r --arg needle "$needle" --arg newemail "$newemail" '[ (.[] | select(.name != $needle)) , ( .[] | select(.name == $needle) | .email |= $newemail ) ]' data.json

Last edited by progandy (2018-08-24 14:45:36)


| alias CUTF='LANG=en_XX.UTF-8@POSIX ' |

Online

#3 2018-08-24 14:44:17

tony5429
Member
Registered: 2006-03-28
Posts: 1,017

Re: [SOLVED] Simpler Solution for jq Search-and-Replace?

Sweet! That works; thank you. It does change the order of the data, but that doesn't really matter to me anyway.

Also, I don't think the "-r" flag is necessary.

Last edited by tony5429 (2018-08-24 14:49:58)

Offline

#4 2018-08-24 14:46:02

progandy
Member
Registered: 2012-05-17
Posts: 5,184

Re: [SOLVED] Simpler Solution for jq Search-and-Replace?

jq has a conditional statement, so this is better:

 jq -r --arg needle "$needle" --arg newemail "$newemail" 'map(if (.name == $needle) then .email = $newemail else . end )' data.json

| alias CUTF='LANG=en_XX.UTF-8@POSIX ' |

Online

#5 2018-08-24 14:51:11

tony5429
Member
Registered: 2006-03-28
Posts: 1,017

Re: [SOLVED] Simpler Solution for jq Search-and-Replace?

Ah; even better! Again, the -r isn't required.

Offline

Board footer

Powered by FluxBB