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?

Inian
  • 71,145
  • 9
  • 121
  • 139
Ilkay Isik
  • 183
  • 2
  • 11

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
  • 39,105
  • 12
  • 41
  • 62
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
  • 77,979
  • 13
  • 71
  • 125
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
  • 88,177
  • 15
  • 123
  • 150
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
  • 3,247
  • 2
  • 14
  • 26
  • 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