0

This is a small part of the code. I am creating test_args having a variable, which needs to be resolved at a later time, when that variable is defined in that scope, here, inside a for loop.

test_args=""
test_args+='-test.coverprofile=/tmp/coverage${ii}.out'
test_dirs="a b"

ii=0
for d in ${test_dirs[@]}; do
    echo ${test_args}               # actually used as `go test ${test_args}`
    ii=$((ii+1))
done

Current output:

-test.coverprofile=/tmp/coverage${ii}.out
-test.coverprofile=/tmp/coverage${ii}.out

Expected output:

-test.coverprofile=/tmp/coverage0.out
-test.coverprofile=/tmp/coverage1.out

I am open to suggestions for better methods. I need all the files to be created with a different name, so as to prevent overwriting in the loop.

subtleseeker
  • 4,415
  • 5
  • 29
  • 41

2 Answers2

1

What you want is a template. You can use the substitution parameter expansion to achieve that:

#!/bin/bash
test_args=-test.coverprofile=/tmp/coverage%i%.out
test_dirs=(a b)

i=0
for d in "${test_dirs[@]}" ; do
    echo "${test_args/\%i%/$i}"
    ((++i))
done
choroba
  • 231,213
  • 25
  • 204
  • 289
1

Using eval is the usual solution:

#!/bin/bash

test_args=""
test_args+='-test.coverprofile=/tmp/coverage${ii}.out'
test_dirs="a b"

ii=0
for d in ${test_dirs[@]}; do
    eval echo ${test_args}
    ii=$((ii+1))
done

Which results in:

[user@linux ~]$ ./test2.sh
-test.coverprofile=/tmp/coverage0.out
-test.coverprofile=/tmp/coverage1.out

But here's a useful discussion about this topic - I advise reading the question linked on the left and it's answer, although it doesn't quite fully apply to this use case.

Chinoman10
  • 48
  • 5
  • Is there some way to use variable indirection in my case, the way described in the link you shared? – subtleseeker Jul 15 '20 at 10:28
  • I don't think it applies to your use case to be honest. You're stuck with either using 'eval' or a template as @choroba mentioned. – Chinoman10 Jul 15 '20 at 12:09