Mike McDonald <mikemac@mikemac.com> replied to:
+---------------
| hannah@schlund.de (Hannah Schroeter) writes:
| > #! /bin/sh
| > exec sbcl --noinform --noprint --noprogrammer \
| > --eval '(load "foo.lisp")' --eval '(quit)' --end-toplevel-options
+---------------
And since most people who write scripts want to have the whole thing
inline -- not in a separate file -- he countered with:
+---------------
| #! /bin/sh -f
| exec /usr/local/bin/cmucl -quiet -batch \
| -eval '(setq *prompt* "")' -noinit <<\EOF
| (progn
| ;; My code goes here
| (print `hello-world)
| (values))
| EOF
+---------------
But in my experience most people who write scripts want them
in-line *and* want to be able to access the normal inherited
standard-input when the script runs (say, to interact with the
user, or with a piped stdin), which Mike's approach precludes.
Here's the gross, ugly, smelly hack I've been using with CMUCL &
CLISP (with minor variations) to provide both at the same time:
% cat ~/bin/hello_cmucl
#!/bin/sh -f
exec /usr/local/bin/cmucl -eval \
"(progn ; double the backslashes for 'sh'
(set-dispatch-macro-character #\\# #\\!
(get-dispatch-macro-character #\\# #\\| ))
(defvar *script-name* \"$0\")
(defvar *script-args* \"$*\")
(load *script-name* :verbose nil))"
|# ; close the block comment [CLISP needs "!#" here]
(format t "Hello world!~%Script = ~S~%Args = ~S~%"
*script-name* *script-args*)
;(format t "~%Input a number: ") ; oops, not if piped
(let ((x (read)))
(format t "~S squared = ~S~%" x (* x x)))
(quit)
% echo 23.45 | hello_cmucl foo bar "baz gorp"
Hello world!
Script = "/u/rpw3/bin/hello_cmucl"
Args = "foo bar baz gorp"
23.45 squared = 549.9025
%
-Rob
p.s. The main problem remaining with the above is Unix command-line
arguments with spaces in them (e.g., "baz gorp"), since the "$*"
doesn't distinguish between inter- and intra-arg whitespace. The
usual Unix solution here would be to use "$@", e.g.:
"(progn ...
(defvar *script-args* '#(\"$@\")) ; build a vector of strings
...)"
but that doesn't work because the inter-arg quotes [or more precisely,
the <quote><space><quote> sequences] that "$@" introduces don't get
backslash-quoted here, and thus break the string argument to "-eval"
in the middle, causing a premature EOF. (Oops!)
-----
Rob Warnock, 31-2-510 rpw3@sgi.com
SGI Network Engineering <URL:http://reality.sgi.com/rpw3/>
1600 Amphitheatre Pkwy. Phone: 650-933-1673
Mountain View, CA 94043 PP-ASEL-IA