whb@vax135.UUCP (Wilson H. Bent) (09/16/87)
[ The line-eater lives! Probably because people keep feeding it...] Given that these files are executable, why does this fail: #!/bin/awk { print $1 } when this works: #!/bin/sh /bin/awk '{ print $1 }' FYI: tested under two BSD variants (sorry, no SysV): Sun UNIX 4.2 Release 3.3 Ultrix V2.0-1 System #1: Wed Jul 15 10:28:13 EDT 1987 -- Wilson H. Bent, Jr. ... ihnp4!hoh-2!whb AT&T - Bell Laboratories (201) 949-1277 Disclaimer: My company has not authorized me to issue a disclaimer.
chris@mimsy.UUCP (09/17/87)
In article <1881@vax135.UUCP> whb@vax135.UUCP (Wilson H. Bent) writes: >Given that these files are executable [by his 4.2BSD-based test >systems], why does this fail: > > #!/bin/awk > { print $1 } > >when this works: > > #!/bin/sh > /bin/awk '{ print $1 }' The two are not equivalent. The former runs /bin/awk with argv[1] set to the path name of the executable file (the awk script) and argv[2] through argv[n] as the `regular' argument list. The latter runs /bin/sh with argv[1] set to the path name of the executable (the shell script) and argv[2] .. argv[n] as the `regular' list. Assuming there were no other arguments, this makes argv[2] nil (or, if you prefer, (char *)0). In the first version, awk takes this argv[1] and attempts to parse it as a program: `syntax error near line 1'. In the second version, the shell takes this argv[1] and interprets it. It runs /bin/awk, this time with argv[1] being the string `{ print $1 }'. The shell does the proper thing because it assumes that, unless otherwise specified via flags, an argument names a file that is to be run. Awk fails because it assumes that, unless otherwise specified via flags, an argument is a literal awk program. Fortunately, it takes only one flag (`-f') to override this: #! /bin/awk -f { print $1 } Since one is allowed only one argument, this also works: #! /bin/awk NR > 1 { print $1 } except that it does something else entirely. Here awk's argv[1] is the string `NR > 1 { print $1 }' which is a valid awk program, and, if there were no other arguments, would be applied to stdin. There is at least one other argument: argv[2] is the name of the awk file. This makes awk print the first word of all but the first line of the file---much like `tail +2'. Awk, however, can read multiple files: #! /bin/awk NR > 1 { print } Heading that goes at the front of some sort of special report format. Running this executable and naming all the files that list the format concatenate this heading and the other files. If this is in a file called `addhead', running `addhead foo bar baz' prints the four heading lines above, followed by the contents of file foo, then bar, then baz. Note that no lines of foo, bar, or baz are skipped as NR is not reset when awk changes files. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
guy@gorodish.UUCP (09/17/87)
> Given that these files are executable, why does this fail: > > #!/bin/awk > { print $1 } Because, if this file is called "foo", and you say "foo", it is as if you had said "/bin/awk foo". This tells it to read "foo" as its *input* file, not as its *program* file, and gives it no program; since it had no program, it issues its all-purpose error message "awk: syntax error near line N" followed by "awk: bailing out near line N". A "#!" script is run by taking the argument list to the original "exec", shifting it right by one, sticking in the name of the script at the left and, if an argument appeared on the "#!" line, shifting the list right one more and sticking that argument in on the front. Thus, if "foo" contained #! /bin/awk -f { print $1 } saying "foo" would run "/bin/awk -f foo", which is what you want. > FYI: tested under two BSD variants (sorry, no SysV): > Sun UNIX 4.2 Release 3.3 > Ultrix V2.0-1 System #1: Wed Jul 15 10:28:13 EDT 1987 Most System V systems have probably not picked up "#!" - none of AT&T's have, as far as I know - so it would have been hard to test it there. Note, though, that the SunOS 3.3 "awk" is a bug-fixed version of the S5R2 "awk" (which is noticeably faster than the "awk" that comes with 4BSD, which is somewhere between the V7 and S5R2 one along the "awk" timeline). Guy Harris {ihnp4, decvax, seismo, decwrl, ...}!sun!guy guy@sun.com
ballou@brahms.Berkeley.EDU.UUCP (09/18/87)
In article <1881@vax135.UUCP> whb@vax135.UUCP (Wilson H. Bent) writes: >[ The line-eater lives! Probably because people keep feeding it...] > >Given that these files are executable, why does this fail: > > #!/bin/awk > { print $1 } > >when this works: > > #!/bin/sh > /bin/awk '{ print $1 }' > The semantics of '#!' are as follows. A command line is constructed by taking the text immediately following the #! (up to some limit which, I believe, is 30 characters), appending a space, then copying the command line which invoked the shell script. So, assuming in both cases the shell script file name is 'foo', the first case behaves as: /bin/awk foo while the second case behaves as: /bin/sh /bin/awk '{ print $1 }' In the second case, the shell forks a process with command line /bin/awk '{ print $1 }' The first case leaves awk with no program (since a file containing a program must be specified as -f filename). -------- Kenneth R. Ballou ARPA: ballou@brahms.berkeley.edu Department of Mathematics UUCP: ...!ucbvax!brahms!ballou University of California