-2

When running the script below, I get an error:

The script is:

clear
echo "Enter a num"
read num 
if [ "$num" -ge 0]; then
    f=1
    i=1
    while [ $i -le "$num" ]; do
    f=`expr $f \* $i`
    i=`expr $i+1`
    done
echo "The factorial of $num is $f"
else
echo "Enter positive number"
fi

Errors:

Enter a num
5
prog4: 5: [: missing ]
Enter positive number

Thankyou

  • 2
    I don't see a question here. I also don't see how this is an Ubuntu issue, as it's a pure generic coding question and belongs on Stack Overflow, not here. – Thomas Ward Apr 9 '15 at 16:01
  • you forgot the backtick at the end of f=`expr .... And use indentation. – muru Apr 9 '15 at 16:02
  • 2
    I'm voting to close this question as off-topic because problems due to typos are hardly useful. – muru Apr 9 '15 at 16:06
  • 2
    @RahulGohrani bash questions are perfectly on topic here, don't worry. Just next time, write an actual question and use a more descriptive title. You should also mention the shell you're using (usually bash). Anyway, if the answer solved your issue, please accept it and then ask a new one for the next error. – terdon Apr 9 '15 at 16:10
  • 1
    Just a suggestion, try not to use back-ticks . Instead prefer $(). UPDATE: The reason for not using is mostly because they are easier to miss. – tusharkant15 Apr 9 '15 at 16:37
4

There are a few errors in this script. They all relate to command-line syntax, most for bash, but in one case for the separate expr utility. In summary:

  • The original problem related to an unmatched ` in a backquote expression (and more generally, how to close a backquote expression and how newlines inside backquote expressions are handled by the shell).
  • Other syntax errors preventing your script from working properly relate to argument parsing in the [ construct and the expr command.

See below for details.

The Original EOF in backquote substitution Error

As Florian Diesch says (and in Helio's answer also), the original problem was a missing ` at the end of the first backquoted expr ... command. However, the more interesting aspect of this question is why do you get that error message? This is not merely a matter of idle curiosity--understanding that helps you comprehend this and other error messages in the future.

EOF stands for end-of-file and it means there are no more data available to read--in this case, text for the bash interpreter to read. EOF is not inherently an error condition, but when an EOF is an error it usually means the interpreter thinks your program has ended prematurely--it was anticipating something, which never occurred in your program.

If the error message had said the error was an end of line in the backquote substitution, you would probably have immediately recognized the problem (provided you know that ` is called a backquote and and command substitution using a backquoted construct is also called backquote substitution).

Why does bash think the file ends too soon, rather than the line? This is because you can actually have newlines (i.e., line breaks) inside a backquote expression:

ek@Io:~$ file `which vim
> `
/usr/bin/vim: symbolic link to `/etc/alternatives/vim'

So what's happening is that bash reads the first backquote expression as

`expr $f\* $i
i=`

which is definitely not what you intended!

Then what you intended as the contents of the second backquote expression it sees outside of backquotes, and sees the following as a second backquote expression:

`
done
echo "The factorial of $num is $f"
else
echo "Enter positive number"
fi

This is also not at all what you intended, and furthermore there is no closing backquote, which causes bash to report reaching end-of-file while still inside a backquote expression (EOF in backquote substitution).

The solution is not to put a backquote at the very end of the script, of course! Instead, as others have said, simply add the missing backquote where it was supposed to be.

Note, however, that this must be `, same as the opening backquote. Although the strange formatting displayed in the output of some command-line utilities might convey the impression that what begins with ` ends with ', that is not the case. (I noticed that had at one point written a ' rather than ` for the fix.)

Closing a [ Command: The [: missing ] Error

After fixing the first problem, you got a prog4: 5: [: missing ] error.

In bash, [ is a command (and in fact there is even a separate [ executable, as unlike bash some shells don't provide a [ builtin). Blank space must appear between it and its first argument.

Similarly, it is required to pass the closing ] of a [ command as a separate command-line argument. That is, you must have blank space before the trailing ] as well as after the leading [.

The line

if [ "$num" -ge 0]; then

should thus be rewritten to say:

if [ "$num" -ge 0 ]; then

For more details on [ syntax, see the output of help [ and help test.

1+1 vs. 1 + 1

After fixing that problem, you'll get another error, which will look something like this (depending, perhaps, on what version of bash you are running):

bash: [: 1+1: integer expression expected

The problem is that expr does not understand 1+1 is intended to mean "the sum of 1 and 1." It does not simplify it to 2, so the [ command that subsequently examines it doesn't have an integer to evaluate.

Why doesn't the expr utility know 1+1 is supposed to be interpreted as an integer, the sum of 1 and 1? This is because each number and arithmetic operator must be passed as a separate command-line argument to expr:

ek@Io:~$ expr 1+1
1+1
ek@Io:~$ expr 1 + 1
2

To fix this problem, rewrite the line

    i=`expr $i+1`

to instead say:

    i=`expr $i + 1`
1

In the line

f=`expr $f\* $i

a backquote (`) is missing.

1

I found some fails on your code, here is a improved one:

clear

read -p "Enter a number: " number
if [[ "$number" =~ ^[0-9]+$ ]]; then
    factorial=1
    for ((i=1;i<=$number; i++)); do
        factorial=$(($factorial * $i))
    done
    echo "The factorial of $number is $factorial"
else
    echo "Enter positive number"
fi

Here you're the edit list and explaination:

  • You can use read -p "Promt here: " myvar instead of printing the prompt before.
  • To check if the input is a positive integer (only unsigned digits) you can use this awesome bash regex: [[ "$number" =~ ^[0-9]+$ ]] that checks if $numbercontains only digits.
  • I indented the code and made verbose the variable names just for readability.
  • Instead of a while loop, why not a for loop? It's more readable and shortens the code.
  • Why to call expr to handle integers? bash has a amazing arithmetic expansion
  • I have updated the new script. Please check. – Rahul Gohrani Apr 9 '15 at 17:01
  • I updated my post, please check ;-) – Helio Apr 9 '15 at 17:39
  • I shall check this. Thankyou. I submitted an answer as well. – Rahul Gohrani Apr 9 '15 at 17:52
  • Please check mine, I think that will help you to make a clean code. – Helio Apr 9 '15 at 17:55
-2

Got the answer

clear
echo " Enter any number "
read n
temp=$(($n-1))
while [ $temp -gt 1 ]; do
        n=$((n *\ temp))
        temp=$((temp - 1))
done
echo "Factorial of number is $n"

Thankyou everyone.

  • As written, that code contains a mistake and, at least in my version of bash, doesn't actually work. You have *\ in an expression for arithmetic expansion, which yields the error bash: n *\ temp: syntax error: operand expected (error token is "\ temp"). It appears your intent is to escape the * character so it is not treated specially by the shell before being subjected to arithmetic expansion. But inside a $(( )) construct, one does not escape *. So even if you had escaped in the usually correct manner (\*, not *\), you'd get an error. n=$((n * temp)) works. – Eliah Kagan Apr 9 '15 at 18:16

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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