cannot create triangle in shell script with for loop - shell

I am quite new in shell script and trying to make some practice. What I want to do is to get an input from the user and create a triangle by using for loop. For example; if the user types 4 as input then the targeted triangle will be;
1
2
2
3
3
3
4
4
4
4
Here is my code:
num=4 ##Assume num is given by user##
for ((i=1; i<=$num; i++))
do
for ((j=1; j<=i; j++))
do
echo $i
done
echo " "
done
Output:
1
22
333
4444
Is it something related with 'new line' thing? How can I fix it?
By the way, I am using an online shell terminal.
Thank you very much.

echo $i prints the value behind the i variable and a newline. You want to print a newline after all the numbers. Use -n switch.
num=4 ##Assume num is given by user##
for ((i = 1; i <= num; i++))
do
for ((j = 1; j <= i; j++))
do
echo -n "$i "
done
echo
echo
done
Or printf:
num=4 ##Assume num is given by user##
for ((i = 1; i <= num; i++))
do
for ((j = 1; j <= i; j++))
do
printf "%s " "$i"
done
printf "\n\n"
done
Remember to qoute your variables (echo "$i" not echo $i)
No need to use $num inside (( .. )). All names are expanded automagically.
#edit
On revisiting the question I came up with the following oneliner with the same functionality:
num=4
seq 1 "$num" | xargs -n1 seq -s ' ' 1
seq 1 "$num" generates numbers 1 2 .... $num separated by newlines
Then for each number xargs runs seq -s ' ' 1 <number> generating 1 .. number for each number separated by spaces
You can insert double newlines with | sed 's/$/\n/' if needed.

Related

loop in bash does not perform integer comparison properly

I have below code
i=0
for s in / - \\ \|
do
printf "\rWaiting for application start to finish $i $s"
sleep 1
((i++))
if [[ $i -gt 30 ]]
then
break
fi
done
The loop always ends after 3 iterations. Any reason as why?
This might be what you are looking for:
#!/bin/bash
a=('/' '-' '\' '|')
for ((i = 0; i < 30; ++i)); do
printf '\rWaiting for application start to finish %d %s' \
"$i" "${a[i%4]}"
sleep 1
done
echo
My mistake. The for loop which has three arguments is exiting instead of the if condition failing.

Ubuntu bash –eq: binary operator expected - nested for loop

I am trying to make Linux bash for my study homework and I think everything is fine(checked many resources), but still error is showing up (–eq: binary operator expected ). What's wrong in my example?
for (( i=1; i <= 3; i++)) ### Outer for loop ###
do
for (( j=1; j <= 3; j++)) ### Inner for loop ###
do
tot=$(expr $i + $j)
echo „tot value: $tot”
tmp=$(expr $tot % 2)
echo „tmp value: $tmp”
if [ $tmp –eq 0 ]; then
echo –e –n „\033[47m ”
else
echo –e –n „\033[40m”
fi
done
echo –e –n „\033[40m” #### set back background colour to black
echo „” #### print the new line ####
done
You are using the wrong character in –eq. It should be a minus (-), not a hyphen (–). The same goes for the hyphen you use on the echo lines.
Also consider using bash's built-in arithmetic expansion instead of expr and test:
#!/bin/bash
for (( i=1; i <= 3; i++)) ### Outer for loop ###
do
for (( j=1; j <= 3; j++)) ### Inner for loop ###
do
(( tot = i + j ))
echo "tot value: $tot"
(( tmp = tot % 2 ))
echo "tmp value: $tmp"
if (( tmp == 0 )); then
echo -e -n "\033[47m "
else
echo -e -n "\033[40m"
fi
done
echo -e "\033[40m" #### set back background colour to black
done

How to increase tabs count based on for loop index in shell script

Following is my for loop
array=( one two three )
for (( i=0;i<${#array[#]};i++ ))
do
echo -e "\t${array[$i]}"
done
with this script I'm getting the output as
#current output
one
two
three
but my requirement is to increase tabs count based on index of for loop.
#required output
one
two
three
can anyone suggest how to achieve this?
Use an inner loop:
for (( i=0; i < ${#array[#]}; ++i )) ; do
for (( j=0; j<=i; ++j )) ; do
printf '\t'
done
echo "${array[$i]}"
done
or accumulate the tabs in a variable:
for (( i=0; i < ${#array[#]}; ++i )) ; do
t+=$'\t'
echo "$t${array[$i]}"
done
Alternatively, use Perl which has the repetition operator:
perl -E 'say "\t" x ++$i, $_ for #ARGV' "${array[#]}"
try
#!/bin/bash
array=( one two three )
for (( i=0;i<${#array[#]};i++ ))
do
printf %"${i}"s |tr " " "\t"
echo -e "\t${array[$i]}"
done
Demo :
$./test.ksh
one
two
three
$cat test.ksh
#!/bin/bash
array=( one two three )
for (( i=0;i<${#array[#]};i++ ))
do
printf %"${i}"s |tr " " "\t"
echo -e "\t${array[$i]}"
done
$
Explanation :
printf %"${i}"s --> will print space i times.

print 001, 002, ..., 099, 100 instead of 1, 2, 3, ..., 99, 100

I want to print 2 numbers that are in the following format:
001,002,003,...,015,016,017,...,098,099,100
for i in touch {001..100}; do
for j in touch {001..100}; do
if (( $j > $i )); then
echo $i $j
fi
done
done
The loop does what I want it to do.
But the problem is that it prints them without the 0s. For example it prints 1 2, 1 3, 1,4, ..., 99 100.
And I want it to print 001 002, 001 003, 001 004, ... , 099 100.
Does anyone have any idea of how can I fix that?
The retention of leading zeros was added in bash 4; you appear to be using an older version of bash. However, if the 0s were retained, you would have to adjust your comparison to avoid treating the values as octal numbers. (090, for instance, is an invalid octal number.)
for i in {001..100}; do
for j in {001..100}; do
if (( 10#$j > 10#$i )); then
echo $i $j
fi
done
done
Using printf with a C-style for loop would be preferable, though.
for ((i=1; i < 101; i++)); do
for ((j=i+1; j < 101; j++)); do
printf '%03d %03d\n' "$i" "$j"
done
done
Note there is no comparison; the inner loop starts j at a value greater than i.
One possibility would be to use printf:
for i in {1..100}; do
for j in {1..100}; do
if (( $j > $i )); then
printf "%03d %03d\r\n" $i $j
fi
done
done
Use seq:
for i in touch $(seq -w 1 100); do
for j in touch $(seq -w 1 100); do
if (( $j > $i )); then
echo $i $j
fi
done
done
printf could also work.

generating new line for each loop bash

I have this problem about bash output i need to write code that would output:
1
22
333
using loops so far i have this code:
First loop....
for ((i=1; i<=1; i=i+1))
do
echo $i
done
#Second loop....
for ((i=1; i<=2; i++))
do
for ((j=2; j<=2; j++))
do
echo -n $j
done
done
#Third loop.....
for ((i=1; i<=2; i++))
do
for ((j=2; j<=2; j++))
do
echo -e $j
done
done
Problem is it outputs third loop inside the second like
1
223
33
Thanks for any help.
A simple nested for loop is be sufficient to do what you want:
CODE:
for ((i=1; i<=5; i++))
do
for((j=1; j<=$i; j++))
do
echo -n $i
done
echo
done
OUTPUT:
1
22
333
4444
55555
Just output the newline after the first loop ends:
for ((i=1; i<=3; i++)) ; do
for ((j=1; j<=i; j++)) ; do
echo -n $i
done
echo
done
Note that in Perl, you can hide the inner loop in the repetition operator x:
perl -le 'print $_ x $_ for 1 .. 3'
Try two nested for loops with interactive start and finish values read from STDIN like so:
# To make it more interactive
echo -n 'Enter start value: '
read START
echo -n 'Enter finish value: '
read FINISH
# Two nested for loops
for ((I=$START; I<=FINISH; I++))
do
for ((J=$START; J<=$I; J++))
do
echo -n $I
done
echo
done

Resources