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.

3 Answers 3

2

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
Sign up to request clarification or add additional context in comments.

Comments

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.

2 Comments

Is there some way to use variable indirection in my case, the way described in the link you shared?
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.
0

A safer solution than using eval would be declaring the "template" variables inside a function scope, and calling the function to access them just before your main logic.

#!/bin/bash

# these will be initialized after function call
init_args() {
    test_args="-test.coverprofile=/tmp/coverage${ii}.out"
}

test_dirs="a b"
ii=0
for d in ${test_dirs[@]}; do
    init_args           # $ii is now visible to test_args for interpolation
    echo ${test_args}
    ii=$((ii+1))
done

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.