Bash script error: [i: command not found - bash

This program is suppose to accept a number from the user and print that many prime numbers. For some reason the program doesn't work. I am new to bash scripting and this is my first program. To my eyes everything seems to be correct. Please tell me where I went wrong.
echo Enter num
read n
i=2
j=2
for(( i=2; i <= n; i++ ))
do
for(( j=2; j < i-1; j++ ))
do
if [i % j == 0];
then
break
fi
if [i == j];
then
echo " $i"
fi
done
done
This is the output I get
Enter num
20
prime.sh: line 12: [i: command not found
prime.sh: line 18: [i: command not found
prime.sh: line 12: [i: command not found
prime.sh: line 18: [i: command not found
.
.
.
After making the suggested changes
read -p "Enter a number : " n
i=2
j=2
for(( i=2; i <= n; i++ ))
do
for(( j=2; j <= i-1; j++ ))
do
if [ $(( i % j )) == 0 ]
then
break
fi
if [ i == j ]
then
echo " $i"
fi
done
done
I was able to run the program but it didn't produce any result
http://i.stack.imgur.com/Fd1se.png

You need to place a space after the [ because [ is an application.
And you can't make calculations between the brackets. You will need to tell bash it needs to calculate the values. So you would need to change line 11 to if (( i % j == 0 )).

if [i % j == 0]; Should be if [ i % j == 0 ];
Same for the one on line 18

Like the others have said, the [ program needs a space before its parameters, like all programs need a space before their args. This is one reason why I prefer the test builtin to [ with its kludgy syntax requiring a useless ] as the last arg just to make it look pretty and sane.
if test $((i % j)) = 0; then
break
fi

#!/bin/bash
#
# primes
#
read -p "Enter a number: " n
i=2
for (( i=2; i <= n; i++ ))
do
for (( j=2; j*j < i; j++ ))
do
if ((i % j == 0))
then
echo "no prime, $i divider: "$j
break
fi
done
done
updated, after realizing (thanks Will Ness), that all primes up to INPUT are searched.
i needs to run to √(n) only.

Related

if elif not working properly for else clause in bash script

I am facing an issue using if elif in bash ,my program is written below,i am careful about the spaces
#!/usr/bin/bash
echo "enter a number"
read num
if (( num >= 1 )) && (( num < 10 )); then
echo "sam"
elif (( num >= 10 )) && (( num < 90 )); then
echo "ram"
elif (( num >= 90 )) && (( num < 100 )); then
echo "rahim"
else
echo "tara"
fi
output:
sourav#LAPTOP-HDM6QEG8:~$ bash ifelse2.sh
enter a number
5
sam
sourav#LAPTOP-HDM6QEG8:~$ bash ifelse2.sh
enter a number
15
ram
sourav#LAPTOP-HDM6QEG8:~$ bash ifelse2.sh
enter a number
95
rahim
sourav#LAPTOP-HDM6QEG8:~$ bash ifelse2.sh
enter a number
105
ifelse2.sh: line 11: echo tara: command not found
So every if and elif works except for the else part,I am extra careful about spaces ,however still I am getting an error ,can someone help,thanks in advance
To fix the spotted problem:
perl -i -pe 's/\becho\b\W+\btara\b/echo tara/' ifelse2.sh
For arithmetic, a better way to code
(( num >= 1 )) && (( num < 10 ))
is
(( num >= 1 && num < 10 ))
And please, indent your code properly, especially when asking help to others.

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

Find the index of a number in the fibonacci sequence

I want to find the index of a number in the fibonacci sequence using recursion.
Example : 13 (my input) is the 8th (output) number of the fibonacci sequence
Here is my function :
#!/bin/bash
function fib() {
number=1
cpt=1
if [[ $number -lt $1 ]]
then
compteur=$(($cpt+ 1))
echo $(( $(fib $(($number - 1)) ) + $(fib $(($number - 2)) ) ))
fi
echo $cpt
}
fib $1
I have this error : Wrong symbol near the +
Then I don't know if my logic for the algorithm is good. I don't know if my syntax of how we are calling the function in the recursion in bash is great.
Any help would be appreciated. Thanks !
With recursion, would you please try the following:
#!/bin/bash
# "fib n" returns the nth Fibonacci number (n starts from 0)
fib() {
local n=$1
if (( n == 0 )); then
echo "0"
elif (( n == 1 )); then
echo "1"
else
echo "$(( $(fib "$(( n - 1 ))" ) + $(fib "$(( n - 2 ))" ) ))"
fi
}
input=$1 # user's input as a 1st argument to this script
for (( i = 0; ; i++ )); do # increment the index i starting from 0
f=$(fib i)
(( f >= input)) && break # if "fib i" >= input, then exit the loop
done
if (( f == input )); then # the input is a Fibonacci number
echo "$i"
else
echo "$i (input $input is not a Fibonacci number.)"
fi
By convention, the index starts with "0", then 13 is the 7th Fibonacci number.
Btw if you increase the input number, you'll see the execution of the script takes a while (e.g. please try with 987 as an input).
Here is an alternative without the recursion:
#!/bin/bash
f0=0
f1=1
input=$1
for (( i = 0; ; i++ )); do
(( f0 >= input )) && break
f2=$(( f1 + f0 ))
f0=$f1
f1=$f2
done
if (( f0 == input )); then
echo "$i"
else
echo "$i (input $input is not a Fibonacci number.)"
fi
Although the recursion is mathematically simple and elegant, the number
of computation depends on the implementation. Fibonacci sequence is a
typical example which requires a consideration.
The 1st script includes two problems:
In the 1st recursion, the fib function calls two fib functions.
In the 2nd recursion, four functions are called. The number of computation
reaches O(2**N).
The intermediate values such as fib(n-1) and fib(n-2) are discarded and
calculated again in the next invocation.

Print Fibonacci series using recursion in bash with only 1 variable

I'd like to know how to print Fibonacci series using recursion in bash with only 1 variable.
From what I've done:
fib()
{
i=$1
if (( $i <= 1 ))
then echo 0
elif (( $i == 2 ))
then echo 1
else
echo $(( $(fib $(($i - 1)) ) + $(fib $(($i - 2)) ) ))
fi
}
echo $(fib $1)
I get the correct output of the final iteration, for example if I enter 10 I will get 34, but I'd like to print the whole sequence of numbers, i.e. all the iterations as well. How can I achieve that?
Another way I tried was by:
#!/bin/bash
arr[0]=0
arr[1]=1
for (( i=0; i<=10; i++ ))
do
echo -n "${arr[0]} "
arr[0]=$((${arr[0]} + ${arr[1]} ))
arr[1]=$((${arr[0]} - ${arr[1]} ))
done
echo ""
But obviously here I've used a for loop, but I don't want to use another variable.
Just for (my kind of) fun, this code prints the Fibonacci numbers from the 0th to the 92nd (as defined in Fibonacci number - Wikipedia) with a recursive function that uses no variables:
#! /bin/bash
function fib
{
echo ${3-0}
(($1 > 0)) && fib $(($1-1)) ${3-0} $((${2-1}+${3-0}))
}
fib 92
Some may claim that using the positional parameters ($1, $2, $3) for this is cheating, but then other solutions could be said to be using two variables ($i and $1).
The code takes under 0.01 seconds to run on my (oldish) Linux machine.
The code should work with numbers up to 92 with Bash version 3 or later on any platform. See Bash Number Limit?. Numbers higher than 93 will cause to code to produce garbage results due to arithmetic overflow.
Variables in bash are global by default. You need to make i local explicitly.
fib () {
local i
i=$1
if (( i <= 1 )); then
echo $i
else
echo $(( $(fib $((i-1)) ) + $(fib $((i - 2)) ) ))
fi
}
(Also, your base cases are a little off if you are starting with 0, and 2 need not be a base case; fib 2 can be derived from the base cases fib 0 and fib 1.)
If you want to print each fibonacci value from 1 to $n, I suggest:
fib_r() {
local i=$1
if (( i < 0 )); then
echo "Error: negative numbers not allowed" >&2
exit 1
elif (( i <= 1 )); then
echo $i
else
echo $(( $($FUNCNAME $((i - 1)) ) + $($FUNCNAME $((i - 2)) ) ))
fi
}
fib() {
local i
for (( i = 1; i <= $1; i++ )); do
fib_r $i
done
}
fib 10
outputs
0
1
1
2
3
5
8
13
21
34
It's still one variable, albeit one per function.
I use the bash variable $FUNCNAME in the recursive function so you don't have to hardcode the function name within itself. I got bit by not updating that line when I renamed the function.
Of course your performance will greatly improve if you cache the results: "fib 16" takes, on my VM, about 3.5 sec without caching and about 0.03 sec with caching.
fib_r() {
local i=$1
if (( i < 0 )); then
echo "Error: negative numbers not allowed" >&2
exit 1
elif [[ -n ${fib_cache[i]} ]]; then
echo "${fib_cache[i]}"
elif (( i <= 1 )); then
echo $i
else
echo $(( $( $FUNCNAME $((i - 1)) ) + $( $FUNCNAME $((i - 2)) ) ))
fi
}
fib_cache=()
fib() {
local i
for ((i=1; i<=$1; i++)); do
fib_cache[i]=$(fib_r $i)
echo "${fib_cache[i]}"
done
}

Numerical if statement in a Bash Script using $'s

I have written a short Bash Script:
for j in 0 1 2 3 4 5
do
for (( i=$j; i <= 5; i++ ));
do
if [ $(($(($i - $j)) > 1)) ]; then
echo "True"
else
echo "False"
fi
done
done
I expect this script to output a mixture of Trues and Falses however it only outputs Trues. I have checked and seen that $(($(($i - $j)) > 1)) is correctly producing 0s and 1s as it is supposed to but apparently the if statement is not registering these and always assumes "True".
Am I missing something in my code?
Thank you very much
James
Your script is checking if [ 0 ] and if [ 1 ] which isn't what you think. It will always return true because it is checking that the length of the string 0 and 1 is not zero.
Change it to:
for j in {0..5}
do
for (( i=j; i<=5; i++ ))
do
if (( i - j > 1 ))
then
echo True
else
echo False
fi
done
done
Note that the use of the $ prefix for variables within ((...)) is optional.
You're using if incorrectly, you're testing for string length when you want an arithmetic comparison:
for j in {0..5}; do
for i in $(seq $j 5); do
if (( i - j > 1 )); then
echo "True"
else
echo "False"
fi
done
done

Resources