0

I have several .json files similar to this.

{
    "AcquisitionNumber": 1,
    "TotalReadoutTime": 0.035,
    "IntendedFor": "func/sub-02_task-rest_run-01_bold.nii.gz"
}

I want to change the sub number in the "IntendedFor" line using a bash variable, looping over different subs.For example if sub is 03:

sub=03
echo $sub
03

How can I change the value of sub-02 to sub-03 using this bash variable?

oguz ismail
  • 1
  • 16
  • 47
  • 69
Ilkay Isik
  • 203
  • 4
  • 14

4 Answers4

5

Use :

jq --arg sub "$sub" '.IntendedFor |= sub("(?<=sub-)[^_]+"; $sub)' file

See this online example

Note that your jq binary must be compiled with regex support in order to use sub function.

And, you can implement inline editing using a for loop and temporary files:

sub=03

for jsonfile in *.json; do
    tempfile=$(mktemp -u)
    jq --arg sub "$sub" '.IntendedFor|=sub("(?<=sub-)[^_]+";$sub)' "$jsonfile" > "$tempfile"
    mv "$tempfile" "$jsonfile"
done
oguz ismail
  • 1
  • 16
  • 47
  • 69
2

With jq and bash:

value=$(jq -r '.IntendedFor' file)
new_value="${value/sub-02/sub-03}"
jq --arg new "$new_value" '.IntendedFor |= $new' file

Output:

{
  "AcquisitionNumber": 1,
  "TotalReadoutTime": 0.035,
  "IntendedFor": "func/sub-03_task-rest_run-01_bold.nii.gz"
}
Cyrus
  • 84,225
  • 14
  • 89
  • 153
1

Using sponge (part of moreutils):

for f in *.json; do
  jq --arg sub "$sub" '.IntendedFor |= sub("/sub-[^_]+";"/sub-"+$sub)' "$f" | sponge "$f"
done

In any case, a simple regex suffices.

sponge for Windows

See:

peak
  • 105,803
  • 17
  • 152
  • 177
0

There are better ways of doing this, but there is a bash-solution:

#!/bin/bash
fromstring="sub-02"
tostring="sub-03"

while read line; do
    case "$line" in
    (*IntendedFor*) echo $(line/$fromstring/$tostring) ;;
    (*)  echo $line ;;
    esac
 done < JSONfile
Ljm Dullaart
  • 4,273
  • 2
  • 14
  • 31
  • I didn't downvote, but your use of `cat` is a *UUOc` (Unnecessary Use Of `cat`)*. Unless you are concatenating files, if you find yourself doing `cat somethingelse`, then it is probably a UUOc. Here using *redirection*, e.g. `while read line; do ... done – David C. Rankin Oct 07 '18 at 19:36
  • As I said, "There are better ways of doing this". But I thought it to be a nice puzzle for doing it in bash only. I removed the `cat` from the answer, which makes it work completely in `bash`, without external programs. – Ljm Dullaart Oct 08 '18 at 17:37
  • should this have the syntax `${variable//pattern/replacement}`, see https://stackoverflow.com/q/13043344/3208553 – Luke Schoen Dec 25 '22 at 21:56