You are not logged in.
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
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 ' |
Offline
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
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 ' |
Offline
Ah; even better! Again, the -r isn't required.
Offline