[net.unix-wizards] /bin/sh feature?

hartley@uvm-cs.UUCP (Stephen J. Hartley) (07/07/84)

Here is a "feature" of /bin/sh that tripped me up for a while.  A beer to
the first wizard to figure this one out (you have to come to Burlington, VT
to collect, though).  The following shell script does nothing, prints no
messages, and changes no files:

	: Daily uucp script
	: assumes you have subdirectories.
	: modified to save another day's LOGFILE
	SPOOL=/usr/spool/uucp
	mv $SPOOL/LOGFILE.old $SPOOL/LOGFILE.older
	mv $SPOOL/LOGFILE $SPOOL/LOGFILE.old
-- 
"If that's true, then I'm the Pope!"		Stephen J. Hartley
USENET:	decvax!dartvax!uvm-gen!uvm-cs!hartley	The University of Vermont

gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (07/09/84)

That's what you get for using : as a comment character.
I'll collect my beer later.

goldfarb@ucf-cs.UUCP (Ben Goldfarb Esq.) (07/09/84)

This points out the hazard of using ':' for a comment delimiter instead
of '#'.  The shell DOES interpret special characters like quotes and
parentheses after the ':', whereas everything on a line after a '#' is
ignored (at least on 4.1bsd systems).  Thus, in your example the apostrophe 
is taken as the start of a quoted literal which never ends.  I've seen
similar problems here and so I advise my shell programmers to use '#'
as the comment delimiter.  I'd be interested in hearing whether this is
indeed a bug or feature.
				Ben Goldfarb
				{duke,decvax,princeton}!ucf-cs!goldfarb

chris@pixutl.UUCP (chris) (07/09/84)

Your problem is:

	: modified to save another day's LOGFILE

If you replace this line with

	: "modified to save another day's LOGFILE"

or
	
	# modified to save another day's LOGFILE

it should work fine. The problem is that sh parses comment lines starting with
a ":" (don't ask me why...) and waits for the closing "'".

	Chris

-- 


 Chris Bertin            :         (617) 657-8720 x2318
 Pixel Computer Inc.     :
 260 Fordham Rd.         :  {allegra|ihnp4|cbosgd|ima|genrad|amd|harvard}\
 Wilmington, Ma 01887    :     !wjh12!pixel!pixutl!chris

dave@csu60.OZ (Dave Horsfall) (07/09/84)

    Relay-Version: version B UNSW 1.0 3/14/84; site csu60.OZ
    Posting-Version: version B 2.10.1 6/24/83; site uvm-cs.UUCP
    From: hartley@uvm-cs.UUCP (Stephen J. Hartley)
    Date: Fri, 13-Jul-84 07:19:32 AEST
    Newsgroups: net.unix-wizards
    Subject: /bin/sh feature?
    Message-ID: <274@uvm-cs.UUCP>
    Path: csu60!elecvax!basser!munnari!mulga!decvax!dartvax!uvm-gen!uvm-cs!hartley
    Date-Received: Mon, 9 Jul 84 01:22:58 AEST
    Organization: University of Vermont
    Lines: 14
    
    Here is a "feature" of /bin/sh that tripped me up for a while.  A beer to
    the first wizard to figure this one out (you have to come to Burlington, VT
    to collect, though).  The following shell script does nothing, prints no
    messages, and changes no files:
    
    	: Daily uucp script
    	: assumes you have subdirectories.
    	: modified to save another day's LOGFILE
    	SPOOL=/usr/spool/uucp
    	mv $SPOOL/LOGFILE.old $SPOOL/LOGFILE.older
    	mv $SPOOL/LOGFILE $SPOOL/LOGFILE.old
    -- 
    "If that's true, then I'm the Pope!"		Stephen J. Hartley
    USENET:	decvax!dartvax!uvm-gen!uvm-cs!hartley	The University of Vermont

The single string quote?

matt@ucla-cs.UUCP (07/10/84)

You have a single quote in your script.
This script is equally uninteresting:

: this isn't interpreted by sh
: because of the single quote
echo this is not printed

		- Matt
-------
UUCP:	{ucbvax,ihnp4}!ucla-cs!locus.matt
ARPA:	matt@ucla-locus

guy@rlgvax.UUCP (Guy Harris) (07/10/84)

> The problem is that sh parses comment lines starting with a ":" (don't
> ask me why...) and waits for the closing "'".

The reason is simple - a line starting with a ":" isn't a comment in the
sense that most programming languages use the word "comment".  ":" is a
built-in command in the shell that does nothing.  Think of it as equivalent
to "echo >/dev/null 2>&1".  It returns an "exit status" of 0 (true).  As
such, it's useful when doing "while true" (since it's built-in, it's faster
than "true" which is a shell file) and useful when you want something like

	if ! cmp -s $1 $2
	then
		diff $1 $2
	fi

which compares two files and, if unequal, "diff"s them.  Unfortunately, you
can't negate the exit status of a "list" in an "if", so you have to do
something like

	if cmp -s $1 $2
	then
		:
	else
		diff $1 $2
	fi

(Yes, I know you could run the "cmp" and then do a

	if test $? -ne 0

but that's *UG*ly.)

Fortunately, every Bourne shell except the V7 shell supports *real* comments,
done with "#".  Everything following the "#" on the line is ignored, even by
the shell's lexical analyzer.

	Guy Harris
	{seismo,ihnp4,allegra}!rlgvax!guy

dave@rlgvax.UUCP (Dave Maxey) (07/10/84)

Oh, really?!?! I've seen that before. Several people will tell you that
using single quotes inside : commented lines in /bin/sh is just a very
bad idea. Since I suspect that a lot of people will reply to this one
(needlessly filling up unix-wizards with more articles to wear down our
'n' keys with), you can send us each one molecule of alchohol from that
beer. That should be fair.

:-) (Just dave's (oops!) comment)

			- Dave Maxey (alias tbm)
			{seismo,mcnc,brl-bmd,allegra}!rlgvax!dave

mss@sb1.UUCP (MERLE SIMPKINS) (07/10/84)

....

Your mv commands are trying to use non-existant variables such as:
"$XXXX.XXXX.XXX". What you need is "${XXXX}/XXXX.XXX".  The 
brackets allow substitution of your variable with the rest of the 
path name appended.

		M. S. Simpkins

ted@usceast.UUCP (07/10/84)

<: a do nothing bug line>

>This points out the hazard of using ':' for a comment delimiter instead
>of '#'.  

>... I advise my shell programmers to use '#'
>as the comment delimiter.
>				Ben Goldfarb
>				{duke,decvax,princeton}!ucf-cs!goldfarb

Good advice, unless you have a fairly vanilla V7 or you are trying
to write portable shell scripts. In the original bourne shell the
# for comments did (does) not exist.
		
			Ted Nolan		..usceast!ted
-- 
--------------------------------------------------------------------------------
Ted Nolan                               ...decvax!mcnc!ncsu!ncrcae!usceast!ted
6536 Brookside Circle                   ...akgua!usceast!ted
Columbia, SC 29206                      ("Hid the bell with a blot, she did")
--------------------------------------------------------------------------------

bet@ecsvax.UUCP (07/12/84)

> This points out the hazard of using ':' for a comment delimiter instead
> of '#'.  The shell DOES interpret special characters like quotes and
> parentheses after the ':', whereas everything on a line after a '#' is
> ignored (at least on 4.1bsd systems).  Thus, in your example the apostrophe
> is taken as the start of a quoted literal which never ends.  I've seen
> similar problems here and so I advise my shell programmers to use '#'
> as the comment delimiter.  I'd be interested in hearing whether this is
> indeed a bug or feature.
> 				Ben Goldfarb
> 				{duke,decvax,princeton}!ucf-cs!goldfarb

Sounds like useful behavior; by preceeding a statement with a colon it gets
commented out even if it is continued on the next line, no?

					Bennett Todd
					...{decvax,ihnp4,akgua}!mcnc!ecsvax!bet

jim@ism780b.UUCP (07/14/84)

#R:uvm-cs:-27400:ism780b:28500002:000:420
ism780b!jim    Jul  9 10:26:00 1984

>        : Daily uucp script
>        : assumes you have subdirectories.
>        : modified to save another day's LOGFILE
>        SPOOL=/usr/spool/uucp
>        mv $SPOOL/LOGFILE.old $SPOOL/LOGFILE.older
>        mv $SPOOL/LOGFILE $SPOOL/LOGFILE.old

Since ":" is *not* a comment character (rather, it is a command which does
nothing), that "'" starts a quoted string which is terminated by EOF.
Use "#" for comments.

crl@pur-phy.UUCP (Charles LaBrec) (07/16/84)

The problem with using '#' as a comment character is that it is non-portable
to v7 (and earlier) systems (I'm not sure about Sys III/V).  In these, the
only way to add a comment is the ':' command (and using quotes to protect
the string).  A further peeve about '#' is that, at least on 4.2 BSD,
saying 'rm #*' doesn't work from the tty in sh since the '#' makes the
rest of the line be treated as a comment.  Csh does not allow '#' from 
the terminal.

Charles LaBrec
UUCP:		pur-ee!Physics:crl, purdue!Physics:crl
INTERNET:	crl @ pur-phy.UUCP

lee@haddock.UUCP (07/18/84)

#R:uvm-cs:-27400:haddock:16800019:000:484
haddock!lee    Jul 15 01:15:00 1984

The shell does more than just parse command lines using the ":" (do nothing)
command.  Because it treats the line as a command, side effects of the
command are NOT "commented out".  For example, try

	: `echo foo >/dev/tty` thud

and you will find that "foo" appears on your terminal.  Therefore, it is
only in a very weak (expensive) sense that the ":" command can be considered
a comment at all.  It is much more accurate to think of it like the "true"
command -- trivial but real.

mwm@ea.UUCP (07/19/84)

#R:uvm-cs:-27400:ea:13500021:000:1019
ea!mwm    Jul 18 17:25:00 1984

/***** ea:net.unix-wizar / pur-phy!crl / 12:26 am  Jul 16, 1984 */
A further peeve about '#' is that, at least on 4.2 BSD,
saying 'rm #*' doesn't work from the tty in sh since the '#' makes the
rest of the line be treated as a comment.  Csh does not allow '#' from 
the terminal.

Charles LaBrec
UUCP:		pur-ee!Physics:crl, purdue!Physics:crl
INTERNET:	crl @ pur-phy.UUCP
/* ---------- */

How long are people going to keep spreading that silly rumor? It just flat
isn't true. Csh is smart enough to realize that "#<non-blank>" or
"<non-blank>#" are *not* comment markers. Hence "lpr -#3" does what you
want, and causes three copies of your output to get printed.

To verify that "rm #*" would work, I did the present the following (from a
4.2 mtxinu binary):

	Script started on Wed Jul 18 17:22:13 1984
	% ls #*
	No match.
	% foreach i (1 2 3 4)
	? 	cp /dev/null #$i
	? 	end
	% ls #*
	#1	#2	#3	#4
	% rm #*
	% ls #*
	No match.
	% ^D
	script done on Wed Jul 18 17:22:50 1984

Looks like the "rm #*" works to me.

	<mike

geoff@callan.UUCP (07/20/84)

Regardless of the fact that there was an unmatched quote on the line with
the colon, why doesn't /bin/sh complain about the "unterminated" string?  I
don't especially mind it continuing past the unescaped newline (although
even that feature is poor design), but uncomplainingly taking the end of the
file as a matching quote is just plain sloppy programming--something you
find a lot in the Bourne shell.
-- 

	Geoff Kuenning
	Callan Data Systems
	...!ihnp4!wlbr!callan!geoff

chris@umcp-cs.UUCP (07/27/84)

One annoying thing about using quoted ``hereis document'' terminators
is that /bin/sh and /bin/csh demand different conventions.  If you are
using /bin/sh, you must NOT quote the terminator.  For example,

	#! /bin/sh
	cat << 'eof'
	Hi there.
	eof

HOWEVER, if you are using /bin/csh, you HAVE to quote the terminator
(and moreover, in the same way as the original).  The script

	#! /bin/csh
	cat << \eof
	Hi.  I'll bet you're expecting this to be the only line.
	eof
	'e'of
	\eof

prints THREE lines.

[Of course, there's always the self-catting awk script:

	#! /bin/awk NR > 1 { print }

is an executable (4BSD anyway) file which prints itself, except
for the first line.

For more fun, try these scripts:

	#! /bin/rm

	#! /bin/mv

Got any other interesting scripts?]
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci (301) 454-7690
UUCP:	{seismo,allegra,brl-bmd}!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@maryland

crl@pur-phy.UUCP (Charles LaBrec) (07/31/84)

It has been pointed out to me that I said 'csh does not allow # from
the terminal'.  Of course, what I meant to say was that csh does not
allow # to act as the comment character from the terminal.  Ooops!

Charles LaBrec
UUCP:		pur-ee!Physics:crl, purdue!Physics:crl
INTERNET:	crl @ pur-phy.UUCP

bsafw@ncoast.UUCP (07/31/84)

	The EOF being taken as a terminating quote, I agree is bad practice.
But I have had to invoke a subshell of /bin/sh (I normally run csh) to do the
following:

awk '$1 ~ /something/ {do_something}
     $1 ~ /something_else/ {do_something_else} ' <infile >outfile

because awk requires them on separate lines and because it was a one-time job
and I didn't want to have to create a file to -f with.  Just because you're
a Berkeley freak, don't deride useful features of the "old" shell! :-)
(the above probably belongs in net.flame; your turn with the napalm...)

-- 
		Brandon Allbery: decvax!cwruecmp{!atvax}!bsafw
		  6504 Chestnut Road, Independence, OH 44131

		  Witness, n.  To watch and learn, joyously.

jim@ism780b.UUCP (08/01/84)

#R:uvm-cs:-27400:ism780b:28500003:000:643
ism780b!jim    Jul 13 20:08:00 1984

> Your mv commands are trying to use non-existant variables such as:
> "$XXXX.XXXX.XXX". What you need is "${XXXX}/XXXX.XXX".  The
> brackets allow substitution of your variable with the rest of the
> path name appended.

Well, there had to be someone who didn't know the right answer,
so they had to give the wrong answer.  So much for wizardry.
Please, people, don't give answers unless you *know* they are
right, or at least indicate that you aren't sure.  And, if you
aren't positive, *try it out first*.  The number one qualification
for a true wizard is that s/he has tested her/his spells.

-- Jim Balter, INTERACTIVE Systems (ima!jim)

jim@ism780b.UUCP (08/01/84)

#R:uvm-cs:-27400:ism780b:28500004:000:334
ism780b!jim    Jul 14 13:11:00 1984

> Sounds like useful behavior; by preceeding a statement with a colon it gets
> commented out even if it is continued on the next line, no?

Yes, but you have to keep in mind that it is syntactically a command so, e.g.,

: (

does not work ("sh: syntax error at line 1: `(' unexpected").

-- Jim Balter, INTERACTIVE Systems (ima!jim)