Subject: Re: simple shell test question
To: Rob Windsor <windsor@warthog.com>
From: Greg A. Woods <woods@weird.com>
List: netbsd-users
Date: 06/06/2002 13:21:03
[ On Thursday, June 6, 2002 at 00:54:43 (-0500), Rob Windsor wrote: ]
> Subject: Re: simple shell test question 
>
> On Thu, 06 Jun 2002 05:48:59 -0000, verily did Jim Breton write:
> 
> > In my travels I have often seen shell syntax like the following:
> 
> > [ x"$VAR" != x"value" ]
> 
> > What is the point of doing that instead of the following?
> 
> > [ "$VAR" != "value" ]
> 
> > Does the 'x' have some special meaning?  (If so, are there any other
> > characters with special meanings?)
> 
> > I have checked two books in my stash and neither of them mentions any
> > use of this syntax that I can see.
> 
> In the old (cough, "SunOS") days, "" was processed by test(1) such that if 
> $VAR was empty, test(1) would barf (erroring out your script), only seeing 
> [ != "value" ].  The fix/hack was to put a prefixing `x' ahead of the 
> quotes.

Ah, no, not exactly.  The "test" command won't bail out when a parameter
for the "=" or "!=" operator is empty.  That's the reason quotes are
used, not the reason for the leading 'x' or '.' or whatever.

In the ancient days when this convention was invented (perhaps by Henry
Spencer, or maybe Guy Harris, or someone like that, though Henry was the
first I remember to use it pedantically), programmers discovered that
when a variable used in a "test" expression contained user-supplied data
then it was necessary to protect the expression from being accidentally
interpreted as an option instead of a value if the variable expansion
resulted in a leading '-' appearing on the value.

Note too that, as you said, the result would sometimes cause an error
message to be printed by "test", but sometimes it would also simply
result in a silent failure when the test returned the incorrect exit
code.

> I might add that seeing your example above merely means that someone was 
> in the habit of using x"$foo".

This convention is still necessary.  So far as I can tell POSIX.1 and
similar standards make no claims about the ability of "test" to parse
complex expressions and intuit what the programmer meant when
user-supplied data values begin to appear as operators.  Remember that
"test" does not do the variable expansions, and it does not group the
words on its command line into separate argv[] elements.  Just because
the NetBSD implementations in /bin/test, /bin/ksh, and /bin/sh are
robust in face of some examples of this scenario it doesn't mean all
other standards conforming implementations are too.  (And just because I
can't find an example that trips up the NetBSD implementations doesn't
mean there isn't one that will that I've not discovered yet! :-)

>  SunOS, at one point, also didn't recognize 
> the "!=" operator.  Instead, you had to use [ ! x"$VAR" = x"value" ].

I don't believe that's true, not for any version of SunOS ever.  V7 test
included the "!=" operator right from the very beginning.  Perhaps
you're thinking of some csh brain damage.  There are many other
portability problems with "test" in older Unix variants, but that's not
one of them.

My trusty old "rabbit" book ("Portable C and UNIX System Programming" by
J.E. Lapin, aka Rabbit Software, Prentice Hall, 1987) confirms this by
saying "All versions identically support infix = and !=, prefix !, and
parenthesis (for grouping)."

-- 
								Greg A. Woods

+1 416 218-0098;  <gwoods@acm.org>;  <g.a.woods@ieee.org>;  <woods@robohack.ca>
Planix, Inc. <woods@planix.com>; VE3TCP; Secrets of the Weird <woods@weird.com>