1

I'm having so much troubles trying to create a string that is the result of the concatenation of an array with a bit of addition every time it goes through the loop

# HERE IS THE VALUE OF CHANGELOG.JSON
# [
#   13,
#   14,
#   22
# ]

readarray -t lines <<<"$(cat $1/changelog.json | jq '.[]')"

echo "check if my array is filled"
echo ${lines[0]}
echo ${lines[1]}
echo ${lines[2]}
echo "my array is correctly filled.."

for i in ${!lines[@]}
do
    var2="$var2 | jq '.[$((($i+1)))]=${lines[$i]}'"
    echo "my var2 during loop: $var2"
done

echo "my var2 after loop $var2"

For some reasons, this script give me this as output

$ /bin/bash add-changelog.sh Blupods-front-v3/
check if my array is filled
13
14
22
my array is correctly filled..
'y var2 during loop:  | jq '.[1]=13
' | jq '.[2]=14loop:  | jq '.[1]=13
' | jq '.[3]=22'oop:  | jq '.[1]=13
' | jq '.[3]=22'op  | jq '.[1]=13

do you guys have any idea of how may i make it work ? i've already went through a lot of the solutions on stackoverflow and none of them worked (using += for concatenation) I've heard on other questions this is due to the fact that for/while loop create a subshell but even in the loop the variable doesn't get memorized.. also I don't have any pipe except for the read array at first.

EDIT: Here I add my expected result, maybe it will help you guys help me I am not trying to execute this command right away, i'm just trying to concat a string in a for loop the expected result should be this

echo $var2
| jq '.[1]=13' | jq '.[2]=14 | jq '.[3]=22'
Rakiah
  • 240
  • 2
  • 15
  • What is `var2="$var2 | jq '.[$((($i+1)))]=${lines[$i]}'"` supposed to do? What is the initial value of var2? That assignment would not execute the pipeline if that is what you are expecting. It will simply assign the whole string to var2, and not the result of the pipeline execution. You need `$(...)` to execute the pipeline. – codeforester Nov 24 '17 at 22:17
  • I do not want to execute it right away, i want to concatenate that string and only execute it outside of the loop at the end (the ultimate goal of this is to update a json file) there is no initial value to var2 – Rakiah Nov 24 '17 at 22:24
  • Please see the edit to see what i am trying to achieve – Rakiah Nov 24 '17 at 22:30
  • What do you want to *do* with `$var2`? There is likely a solution that doesn't require dynamically generating a pipeline of multiple calls to `jq`. – chepner Nov 25 '17 at 00:49
  • Something like `jq --slurpfile cl changelog.json '.[:3] = $cl[]' original.json` may do what you want. – chepner Nov 25 '17 at 00:53

2 Answers2

2

It seems the values in the array have \r characters. You can remove them with tr -d '\r'. Actually I suggest to write like this:

lines=($(jq '.[]' < "$1"/changelog.json | tr -d '\r'))

And although your for-loop is correct, it can be improved too:

var2=
for i in ${!lines[@]}; do
    var2="$var2 | jq '.[$((i+1))]=${lines[i]}'"
done
janos
  • 120,954
  • 29
  • 226
  • 236
  • this is not doing anything because there is nothing inside "lines" – Rakiah Nov 24 '17 at 23:01
  • I managed to make it work by doing this instead `lines=($(cat "$1"/changelog.json | jq '.[]' | tr -d '\r'))` the solution you provided at first created a segmentation fault inside jq if you edit your answer i will approve it, Thanks a lot :) – Rakiah Nov 24 '17 at 23:05
  • @Rakiah how about `lines=($(jq '.[]' < "$1"/changelog.json | tr -d '\r'))` ? This should be equivalent, but without a useless `cat` ;-) – janos Nov 24 '17 at 23:58
  • Yes, the second solution without the cat work just like the cat one, but there is still a problem, if my changelog.json file has an array of string containing spaces, the lines array contains much more key than one per value, for some reason the lines array also split everytime it encounter a space, do you have a solution for this aswell ? Thank you anyways – Rakiah Nov 25 '17 at 01:05
  • well a quick search find an answer for me if there is anyone with the same problem https://stackoverflow.com/questions/24628076/bash-convert-n-delimited-strings-into-array this worked, and everything is fine now, Thank you janos – Rakiah Nov 25 '17 at 01:07
0

This might help instead if the respective line in the for loop.

var2="$(echo "$var2" | jq '.[$((($i+1)))]=${lines[$i]}')"
creativecoding
  • 247
  • 2
  • 9
  • I am not trying to execute this command right away, i'm just trying to concat a string in a for loop the expected result should be this please see my edit for what I want to achieve – Rakiah Nov 24 '17 at 22:26
  • @Rakiah: Sorry, I now see what you were aiming for, thanks for your edit. I did some testing and figured, that `-t` for `readarray` didn't have the desired effects for me. In your case, this might case these strange line breaks in your output. However, variable substitution got me further. Could you try using `${lines[$i]//$'\n'/}` in the body of your `for` loop instead of just `${lines[$i]}`? – creativecoding Nov 24 '17 at 22:41
  • Thank you for your time, using this line `var2="$var2 | jq '.[$((($i+1)))]=${lines[$i]//$'\n'/}'"` I get this output `'y var2 during loop: | jq '.[1]=17 ' | jq '.[2]=13 '.[1]=17 ' | jq '.[3]=14'.[1]=17` – Rakiah Nov 24 '17 at 22:46
  • but i do believe that readarray -t is the problem though, because with a normal array created like this `array=(13 17 22)` this give an output that look like much more what i want – Rakiah Nov 24 '17 at 22:48
  • @Rakiah: That looks better! Can you do `var2=""` before the loop? – creativecoding Nov 24 '17 at 22:49
  • @Rakiah: I agree, there is something wrong with `readarray -t` and the compulsory newline provided by `${lines[$i]}`. This thread leads towards a workaround it seems. (Btw: Need to go now, back in a bit.) – creativecoding Nov 24 '17 at 22:56
  • You think so ? i don't even know that's so strange now i get this `' | jq '.[3]=17'op | jq '.[1]=13` and the thing is, i'm only echoing once at the end, like this `echo "my var2 after loop $var2"` where does the "op" come from and why there is no "my var2 after loop" that's really out of my understanding lol – Rakiah Nov 24 '17 at 22:56