0

I have a Bash script where i have calculated many values and stored them in the variables which have a number for each row. For instance, i have a variable named as TC_5 which calculates the value of 5th row of the input csv file. I have calculated all the values and stored in variables which have the naming convention of TC_<Row_No> so that for 200 rows i have values stored in:

TC_1
TC_2
.
.
TC_200

Now, i want to write a loop which could print the values of all these variables together to an external file instead of manually printing them. For this, i am using the while loop as follows:

i=0
while [ "$i" != 201 ]
do
    echo "TC_$i" >> Out
    i=`expr $i + 1`
done

How can i modify the above code in such a way that the echo statement would print the variable TC_<RowNo> to the Out File?

  • Why not use awk/sed? – MatthewRock Sep 22 '15 at 8:03
  • 1
    Do you hear about arrays? – Costas Sep 22 '15 at 8:25
  • Hello Guys, could you please provide your suggestions as answers? I don't want to do it strictly with while loop. Any other option which is faster and better would be appreciated. Of course i have heard about arrays :) – Ankit Vashistha Sep 22 '15 at 9:29
2

Your current script stuck in an infinitive loop, because the condition [ "$i" != 201 ] was always true.

You must increase $i after each iteration and using eval to print the content of TC_<RowNo> variable (but it's not safe):

i=1
while [ "$i" -ne 201 ]
do
    eval printf '%s\\n' "\${TC_$i}"
    i=$((i+1))
done >> "Out"

Note that $i started at 1, the use of -ne for integer comparison and the redirection at the end of while loop.

  • Good point cuonglm. Actually i missed to put the increment statement in the above example. That is present in my main script. Thanks for your answer. I will try it and get back to you. – Ankit Vashistha Sep 22 '15 at 9:06
1

The preferred way to do this sort of thing in bash is to use an array:

TC[1]=something
TC[2]=somethingelse
...
TC[200]=somethingstillelse

i=1
while ((i <= 200)); do
    echo "${TC[i]}" >> Out
    ((i++))
done

But if you really want to embed the indexes in plain variable names, you can use an indirect variable reference:

TC_1=something
TC_2=somethingelse
...
TC_200=somethingstillelse

i=1
while ((i <= 200)); do
    varname=TC_$i    # Need to store the variable name in a variable first
    echo "${!varname}" >> Out    # The ! (and braces) trigger indirect expansion
    ((i++))
done

Note that neither of these features are available in basic POSIX shells like dash. Make sure your script is running under bash, not a generic shell.

-1

I changed your while loop slightly and it worked for me:

i=1
while [ "$i" != 201 ]
do
    echo $TC_$i >> Out
    i=`expr $i + 1`
done

Note the $ in front of TC_$i and the removal of the double quotes. (I included the modification cuonglm suggested for the starting value.)

(Using GNU bash in iTerm on a Mac running High Sierra.)

  • 1
    Really?  That doesn't work for me.   (Are you sure you're using bash?) – G-Man Feb 13 at 2:47
  • ~/CertificateTest/save 499> /bin/sh --version GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17) Copyright (C) 2007 Free Software Foundation, Inc. – J. Van Heuit Feb 13 at 7:34
  • No, $TC_$i would expand to the concatenation of the values of the variables TC_ and i. – Kusalananda Feb 13 at 9:19
  • And yet, it really did work for me on GNU bash... – J. Van Heuit Feb 13 at 17:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.