tags:

views:

779

answers:

6

The code

 #!/usr/bin/awk            

 # Sed and AWK by O'Reilly (p.179)

 # Example of what should happen: factorial 5 gives
 #   factorial
 #   Enter number: 3
 #   The factorial of 3 is 6


 BEGIN {
     printf("Enter number: ")
 }

 $1 ~ /^[0-9]+$/ {
     # assign value of $1 to number & fact
     number = $1 
     if (number == 0) 
         fact = 1
     else
         fact = number

     for (x = 1; x < number; x++)
         fact *=x
     printf("The factorial of %d is %g\n", number, fact)

     exit
 }

 # if not a number, prompt again.
 { printf("\nInvalid entry. Enter a number: ")
 }

I run the command unsuccessfully by

./factorial.awk

I get

/usr/bin/awk: syntax error at source line 1
 context is
         >>>  <<< ./factorial.awk
/usr/bin/awk: bailing out at source line 1

What does the error message mean?

+3  A: 

Possibly a dumb answer but in my terminal I would have to type in:

./factorial.awk

where the file is factorial.awk.

You could edit your path environment variable to include . but ./ should work just fine I think. And adding . to $PATH could prove to be very dangerous in some situations where you would run code that you did not expect to.

Does that work??

EDIT:

./factorial.awk -bash: ./factorial.awk: /usr/bin/gawk: bad interpreter: No such file or directory

That says that it ran the file but could not find the program gawk. Please type in 'which gawk' and then 'which awk'.

Is your first line supposed to be:

#!/usr/bin/awk

Also, just to amuse me, type in:

sudo apt-get install gawk

That will make sure you actually have gawk on your system.

EDIT2: I took a look at your code and this is what I have now. I removed two quotes and a dash.

#!/usr/bin/gawk                                                                                                                                        

# I think we do not need these (p.179) so I comment them out, since I do not know where else to put them.
# The same bug occurs also with them.
#fact = number
#for (x = number -1 ; x > 1; x--)
#    fact *= x

awk # factorial: returns factorial of user-supplied number
    BEGIN {
    printf("Enter number: ")
    }

   $1 ~ /^[0-9]+$/ {
   # assign value of $1 to number & fact
   number = $1 
   if (number == 0) 
       fact = 1
   else
       fact = number
   #loop to multiply fact*x until x = 1
   for (x = number - 1; x > 1; x--)
       fact *= x
   printf("The factorial of %d is %g\n", number, fact)
   #exit -- saves user from typing ^-d
   exit
}

# if not a number, prompt again.
{ printf("\nInvalid entry. Enter a number: ")
}
Robert Massaioli
I get the following errors: http://dpaste.com/37585/
Masi
Is your first line correct? Please see the edit.
Robert Massaioli
The dpaste.com example shows you using 'sudo' to run 'chmod'; that is a dangerous set of practices to get into. Get out of them now, before you break your system catastrophically. For scripts you write, it should never be necessary to use sudo to change the permissions. You should be working in your own territory on your own file where you can change permissions without needing root authority.
Jonathan Leffler
I get the following error http://dpaste.com/37593/
Masi
@Jonathan: Thank you for the piece of information! I have had a practice of decreasing permissions first when I start to debug.
Masi
The code I provided works on my machine but that does not say much. I hope it works for you.
Robert Massaioli
+2  A: 

Check whether there is a file /usr/bin/gawk; if not, use either the path of awk or the correct location for gawk.

Also, did you make the script executable?

And also, do you have the current directory in your PATH?

Jonathan Leffler
The code is now 777. How can you I whether I have the current directory in my PATH or not?
Masi
Well, if PATH=":/bin:/usr/bin:.:/home/me/bin:" and current directory (cwd) = /home/me/bin, then cwd appears 4 times on the path: (1) before the first colon (2) as dot between two colons (3) as /home/me/bin (4) after the last colon. Don't use 777 permission; never make files - especially executable files - publicly writable; worry about whether members of your group should have write permission too. (It could be worse; I know of a makefile that sets perms to 7777 (setuid, setgid, sticky bit!)
Jonathan Leffler
I put the pwd's output to my PATH. I have permissions now 755. I get the following error messages http://dpaste.com/37592/
Masi
Since typing "./factorial.awk" elicits the error "bash: ./factorial.awk: /usr/bin/gawk: bad interpreter: No such file or directory", I conclude that your machine does not have a program /usr/bin/gawk - as suggested in my answer. Locate it...use 'which gawk', and if that fails to produce an answer, then use 'which awk'. If you get a path, use it in place of /usr/bin/gawk. If you don't get a path, then neither awk nor gawk is installed in a directory on you PATH. ...continued...
Jonathan Leffler
...continued... Either it is not on the machine at all (if the worst comes to the worst, use 'find / -name "*awk*"' to locate it) or you need to add the right directory to your path.
Jonathan Leffler
They both seem to be in my Computer: http://dpaste.com/37605/
Masi
I get now the following error message: http://dpaste.com/37606/
Masi
Believe it or not, that is considerable progress. What you are now getting is awk saying "I do not understand shell scripts". ...more to say; life intervenes!
Jonathan Leffler
OK - drop the awk and single quote near the top; drop the matching single quote and trailing dash at the bottom. That should do it.
Jonathan Leffler
+1  A: 

I think that the problem is that you are writing a shell script and passing it to awk for execution. The following is a shell script, hence the #! /bin/sh, so it will be passed to the shell (Bourne-compatible in this case).

#! /bin/sh
awk 'BEGIN { printf("Hello world!\n"); exit }'

The she-bang (#!) line tells the current interpreter which interpreter to pass the script to for execution. You have to pass the script to the awk interpreter so you need to call awk explicitly. This assumes that awk is in your path somewhere.

The following, however, is an awk script.

#! /usr/bin/awk -f
BEGIN {
    printf("Hello world!\n");
    exit
}

The she-bang invokes awk and passes the script as input. You don't need to explicitly invoke awk in this case and you don't have to quote the entire script since it is passed directly to awk.

Think of the she-bang as saying take what follows the she-bang, append the name of the file, and execute it. Wikipedia describes the usage pretty well including some common ways to solve the path to the interpreter problem.

D.Shawley
A: 

I got the script to work in Ubuntu and OS X by running

awk -f factorial.awk

It seems that you cannot run the script as follows although the book says so

./factorial.awk
Masi
You most certainly can run it as "./factorial.awk". The requirements to do this are: (1) it's executable by the user, so "chmod 0700 factorial.awk", (2) the first line of the file is "#! /path/to/awk" so the shell will run awk, (3) the script is executed correctly in the shell with respect to the path so "./factorial.awk" will work, and (4) it is a valid awk script. Having the whole script wrapped in "awk ' ... '" is not valid!
D.Shawley
Thank you for your answers!
Masi
A: 

may be it wasn't that complicated.

#!/usr/bin/awk ---------> #!/usr/bin/awk -f

Joyer
A: 

Here's a recursive version:

#!/usr/bin/awk -f
function f(x) {
    if (x <= 1) return 1
    return (f(x-1) *x)} 

BEGIN {
    printf("Enter number: ")
}

$1 ~ /^[0-9]+$/ {
    printf("The factorial of %d is %d\n", $1, f($1))
    exit
}

{ printf("\nInvalid entry. Enter a number: ")
}
Dennis Williamson