Accessing variable value in BASH for loop - bash

This question already has answers here:
Dynamic variable names in Bash
(19 answers)
Closed 1 hour ago.
I want to assign and print variable values within a for loop in BASH.
My code looks like this:
tea=(A B C D E F G)
c=0
for (( i=1; i<${#tea[#]}; i++ ));
do
eval "var$c=${tea[$i]}";
c=$((c+1));
echo "$var$c" >> example.txt
done
The output I get in my txt file is: 1 2 3 4 5 6. The output I expect is B C D E F G. I don't understand why am I getting this output, am I not assigning values to var$c correctly or this echo command cannot read my variable value? I would appreciate your help a lot.

One approach using a nameref:
tea=(A B C D E F G)
c=0
for (( i=1; i<${#tea[#]}; i++ ));
do
declare -n varC="var$c" # nameref
varC="${tea[$i]}"
c=$((c+1))
echo "$varC" >> example.txt
done
This generates:
$ cat example.txt
B
C
D
E
F
G

Related

Should I use $i or i as array index in Bash Shell? [duplicate]

This question already has answers here:
Arithmetic expansion in array indices - is the dollar sign needed?
(2 answers)
Closed 2 years ago.
$ x=(a b c d e)
$ echo ${#x[*]}
5
$ for ((i=0;i<5;i++)); do echo ${x[$i]}; done
a
b
c
d
e
$ for ((i=0;i<5;i++)); do echo ${x[i]}; done
a
b
c
d
e
$ for ((i=0;i<5;i++)); do echo i; done
i
i
i
i
i
$ for ((i=0;i<5;i++)); do echo $i; done
0
1
2
3
4
I use either $i or i to access array element, all are right?
Why?
Array indices are evaluated in an arithmetic context. Which means that both :
${x[i]}
and
${x[$i]}
are valid.
For instance :
$ x=(a b c d e)
$ echo "${x[0]}"
a
$ i=1
$ echo "${x[i+2]}"
d

How to pass items to bash for loop on multiple lines?

I can do this in bash:
for n in a b c d e ; do
echo $n
done
If a, b, c, d, e turn out to be long lines, without using a separate variable, how do I put them each on a separate line in the for loop syntax?
Split the line with \:
$ for i in a \
> b \
> c \
> d ; do echo $i ; done
a
b
c
d
I'd use a "here document":
while read n; do
echo $n
done <<EOF
some detailed stuff here
other things on the next line, blah blah blah
EOF
Of course in this particular example you can replace the entire while loop with cat but I suppose your real code is more involved.
you can put a b c d e in a file and run a loop over that file.
while read line
do
echo "$line \n"
done < file

Can I output multiple value in bash, like read A B C <<< "1 2 3"?

I am learning bash shell.
I found a command "read" which can deliver multiple values to different variables, like
read A B C ... <<< "1 2 3 ..."
Now I make a function
function echo_multiple_values() {
echo "1 2 3 ..."
}
Do I have a smart way to output multiple values from a function, like
A B C ...=$(echo_multiple_values)
Thank you very much.
You can't do
A B C ...=$(echo_multiple_values)
but you may wish to do something like below :
myfun(){
arr=( {1..3} ) #{a..b} is a bash range
echo "${arr[#]}"
}
read a b c <<<"$(myfun)"
Also, you could do something like below
$alphabets=( {a..z} )
$ nums=( {1..26} )
$ read "${alphabets[#]}" <<<"${nums[#]}"
$ echo $a
1
$ echo $c
3
$ echo $z
26

Declaration of variable with variable in bash [duplicate]

This question already has answers here:
Lookup shell variables by name, indirectly [duplicate]
(5 answers)
Closed 9 years ago.
#!/bin/sh
b=( a b c d )
count=1
for a in ${b[#]}; do
example_$count=$a # how do I declare this variable "example_$count"
echo example_$count; # and how do I echo it
(( count++ ))
done
What I need is something like this:
$example_1=a
$example_2=b
$example_3=c
$example_4=d
For declaring variables, you use eval. For displaying variables, you have two solutions : eval, or Bash syntax ${!var}.
So your script becomes, with only eval :
#!/bin/bash
b=( a b c d )
count=1
for a in ${b[#]}; do
var=example_$count
eval $var=$a
eval echo \$$var
(( count++ ))
done
Or with Bash syntax for display :
#!/bin/bash
b=( a b c d )
count=1
for a in ${b[#]}; do
var=example_$count
eval $var=$a
echo ${!var}
(( count++ ))
done
The most simple solution:
example=( a b c d )
Instead of $example_1, just use ${example[0]}. At first glance, this may not look like what you want. But keep in mind that BASH is a scripting language with a history (= it has many, many quirks). So while it's not exactly what you think you need, it will work as you expect in most cases.
One reason might be that you think that arrays should start with index of 1 (which is a common beginners mistake that causes lots of problems later). But if you insist, you can insert an empty 0 element to simulate the desired behavior:
example=( "" a b c d )
of if you already have the array:
example=( "" "${example[#]}" ) # prepend empty element to existing array

looping over arguments in bash

In bash, I can loop over all arguments, $#.
Is there a way to get the index of the current argument? (So that I can refer to the next one or the previous one.)
You can loop over the argument numbers, and use indirect expansion (${!argnum})to get the arguments from that:
for ((i=1; i<=$#; i++)); do
next=$((i+1))
prev=$((i-1))
echo "Arg #$i='${!i}', prev='${!prev}', next='${!next}'"
done
Note that $0 (the "previous" argument to $1) will be something like "-bash", while the "next" argument after the last will come out blank.
Not exactly as you specify, but you can iterate over the arguments a number of different ways.
For example:
while test $# -gt 0
do
echo $1
shift
done
Pretty simple to copy the positional params to an array:
$ set -- a b c d e # set some positional parameters
$ args=("$#") # copy them into an array
$ echo ${args[1]} # as we see, it's zero-based indexing
b
And, iterating:
$ for ((i=0; i<${#args[#]}; i++)); do
echo "$i ${args[i]} ${args[i-1]} ${args[i+1]}"
done
0 a e b
1 b a c
2 c b d
3 d c e
4 e d

Resources