Nested for Loop in Bash
In this tutorial, we will discuss nested loops in bash. First, we will quickly discuss the different available for
loop formulations in bash. Next, we will discuss the nested for
loop with examples.
Variations of for
Loop in Bash
First of all, let’s look at the syntax of the for
loop in bash:
for var in something
do
command
done
In this syntax, the variable name is the user’s choice. There are multiple options for something
, which we will discuss shortly.
We can write any number of commands inside the for
body. Multiple for
loop variations are available in bash; we will quickly see some below.
for
in the Range of Numbers
We can specify a list of numbers with a for
loop and can iterate on those numbers one by one, as depicted by the following example:
for i in 1 3 8
do
echo $i
done
The loop will iterate on the given list of values (i.e., 1 3 8
). In this particular example, the output will be:
1
3
8
for
in List of Values
We can define a list of values and iterate over the list as follows:
x=(1 3 8)
for i in ${x[@]}
do
echo $i
done
The outcome of this code will be the same as the output of the previous example. In the for
loop statement, the {x[@]}
represents: for every element of list x
.
for
in the Range of a Sequence
We can give a range of values with starting number, followed by a double dot (..
), followed by an ending number. Similarly, we can put another pair of dots followed by a step.
For example, let’s look at the following two example loop formulations:
for i in {1..3}
do
echo $i
done
echo "----------------------"
for i in {1..3..2}
do
echo $i
done
The output of this code will be:
1
2
3
----------------------
1
3
for
in String With Words
We can define a list of words in a string separated by spaces and iterate over the words in the string as follows:
names="Asim Babar Munir Ali"
for name in $names
do
echo $name
done
The output of this code will be given names in separate lines as follows.
Asim
Babar
Munir
Ali
C-Style for
Expression
We can give an expression in the for
loop similar to the for
in C language. See the example:
for ((i=1;i<=5;i++))
do
echo $i
done
It will produce the following output:
1
2
3
4
5
Use of continue
Statement in for
Loop
We can put some conditions in the body of the for
loop, followed by a continue
statement to skip the next body of the loop. See the example:
for ((i=1;i<=5;i++))
do
if [ $i == 3 ]
then
continue
fi
echo $i
done
Due to the if
condition, the loop will skip the echo
command for value 3
; therefore, the output will be: 1 2 4 5
.
Loop Over Command Line Arguments
We can give command line arguments to our bash script and run a for
loop over the arguments separated by spaces. See the example:
for i in $@
do
echo "Script arg is $i"
done
In the first line, the $@
symbol represents a list of arguments separated by spaces. See the output for this example:
bash myscript.sh 13 28
Script arg is 13
Script arg is 28
Loop Over Output of Command
We can run the for
loop over the output of some command. See the example:
for f in $(ls)
do
echo "**** $f *****"
done
This script will take the output of the ls
command and iterate over the values. See example output:
**** first.c *****
**** second.c *****
**** third.c *****
Loop Over Variable Sequence
We can also run some input based on some variable at run time. For this, we can use seq 1 1 $n
, where n
can be a variable. See the example:
n=4
for i in $(seq 1 1 $n)
do
echo -n $i
echo " "
done
Here, I have assigned the value 4
to a variable, whereas it can be some count, like word count etc. See example output:
1
2
3
4
Nested for
Loop in Bash
We have a variety of nested for
loops in bash. According to our requirement, we can create several variations of the nested for
loops (i.e., by combining the available for
loop formulations.
Here, we will see multiple examples with the output:
-
Print the first ten multiples of the first five positive integers.
for number in {1..5} do for n in {1..10} do echo -n $((number*$n)) echo -n " " done echo "" done
The output of this code is:
1 2 3 4 5 6 7 8 9 10 2 4 6 8 10 12 14 16 18 20 3 6 9 12 15 18 21 24 27 30 4 8 12 16 20 24 28 32 36 40 5 10 15 20 25 30 35 40 45 50
-
Print first 10 multiples of list of integers.
for number in 2 5 9 do for n in {1..10} do echo -n $((number*$n)) echo -n " " done echo "" done
The output of this code is:
2 4 6 8 10 12 14 16 18 20 5 10 15 20 25 30 35 40 45 50 9 18 27 36 45 54 63 72 81 90
-
Print numbers in triangle pattern.
for number in {1..5} do for n in $(seq 1 1 $number) do echo -n $n done echo "" done
The output of this code is:
1 12 123 1234 12345
We may get several lines from the command line argument to print a variable-size pattern. See code:
for number in $(seq 1 1 $@) do for n in $(seq 1 1 $number) do echo -n $n done echo "" done
The output of the command
bash pattern2.sh 6
is:1 12 123 1234 12345 123456
Where
patter2.sh
is the name of this script and6
is the command line argument. -
Print a triangle pattern with an asterisk (
*
) or any other character.for number in $(seq 1 1 $@) do for n in $(seq 1 1 $number) do echo -n "*" done echo "" done
The output of the code with argument
4
is:* ** *** ****
-
Print messages multiple times (for emphasis).
messages="Sea_is_rough Don't_go_too_far_in_the_sea Remain_in_the_group Don't_take_kids_inside" for i in 1 2 3 4 5 do for message in $messages do echo $message done echo "----------------------------------" done
The output of this is:
Sea_is_rough Don't_go_too_far_in_the_sea Remain_in_the_group Don't_take_kids_inside ---------------------------------- Sea_is_rough Don't_go_too_far_in_the_sea Remain_in_the_group Don't_take_kids_inside ---------------------------------- Sea_is_rough Don't_go_too_far_in_the_sea Remain_in_the_group Don't_take_kids_inside ---------------------------------- Sea_is_rough Don't_go_too_far_in_the_sea Remain_in_the_group Don't_take_kids_inside ---------------------------------- Sea_is_rough Don't_go_too_far_in_the_sea Remain_in_the_group Don't_take_kids_inside ----------------------------------
-
Print counting from 1 to onward in a single line. You have to print counting till the list of command line arguments.
for number in $@ do for i in $(seq 1 1 $number) do echo -n "$i " done echo "" done
The output of this code for
Bash counting.sh 4 5 8
is:1 2 3 4 1 2 3 4 5 1 2 3 4 5 6 7 8
-
Print multiples of 10 to 20, but don’t print multiples of prime numbers in this sequence.
for number in $(seq 10 1 20) do if [[ $number == 11 || $number == 13 || $number == 17 || $number == 19 ]] then continue fi for n in {1..10} do echo -n $((number*$n)) echo -n " " done echo "" done
The output of this code is:
10 20 30 40 50 60 70 80 90 100 12 24 36 48 60 72 84 96 108 120 14 28 42 56 70 84 98 112 126 140 15 30 45 60 75 90 105 120 135 150 16 32 48 64 80 96 112 128 144 160 18 36 54 72 90 108 126 144 162 180 20 40 60 80 100 120 140 160 180 200
Conclusively, we have a variety of nested for
loops in bash. Therefore, we can use combinations of the available for
loop variations according to our requirements to complete the task.