On Mon, Jan 11, 2010 at 1:01 AM, J.C. Roberts <list-...@designtools.org>
wrote:
> Below is a "test case" ksh shell script to show examples of very minor
> omissions in the ksh(1) man page regarding testing for zero length and
> non-zero length. A patch for ksh.1 is below.
>
> In the script, you'll need to manually fix the assignment of $foo for
> test set #2, since sending a raw null through email is a major pain. I
> have it set below as text '^@' but you'll need to replace it with a
> real null (CTRL-V CTRL-@).

NULs are always silently dropped from strings by the shell, so test
this part of your script duplicates the part where foo is the empty
string.


> Some of the notes on the failures are very generous since the current
> man page does mention some of the caveats but they are mentioned in
> relation to comparison rather than length tests.
...
> @@ -761,6 +761,8 @@
>  .No \&[ Ar str No \&]
>  use
>  .No \&[[ -n Ar str No \&]] .
> +Similarly, testing for zero length should use
> +.No \&[[ -z Ar str No \&]] .

Given the context, this seems unnecessary.  Currently it reads:
                   o   The single argument form of test, which tests if the
                       argument has a non-zero length, is not valid; explicit
                       operators must always be used e.g. instead of [ str ]
                       use [[ -n str ]].

So, the test for "not zero length" that works with [...] but not [[...]] is
    [ ! str ]

...which can be translated using the rule already documented to get
    [[ ! -n str ]]


> +.Pp
> +Additionally, testing for zero length with
> +.Dq if \&[ -z $foo \&]
> +, or testing for non-zero length with either
> +.Dq if \&[ -n $foo \&]
> +, or
> +.Dq if \&[ $foo \&]
> +can also fail if parameter
> +.Dq foo
> +is
> +.Dv NULL
> +, or unset, or contains spaces (i.e.\&
...

(Two nits with your manpage source:
1) Always start sentences at the beginning of a line,
2) Commas and periods should be at the end of the line, albeit *preceeded*
   with a space if the line has a formatting macro.  For example:
    .Dv NULL ,
)


I'm not entirely convinced this change should be made, in part because
it's too narrow.  Problems with arguments to 'test' that are empty or
contain whitespace is not restricted to -z and -n and can just as well
hit the file tests.  Why stop there?  Programs other than 'test' are
affected too!  And don't forget to pass '--' to programs to stop
option parsing when the first positional argument is from a variable.
And use arrays when you need to store multiple values that may contain
whitespace.  And...

Then again, 'test' does seem to be the place where people first slam
into this.  <mumble>

(As a side-note, both the existing "Note" and your proposed addition
are wrong about the unquoted constructs having problems when the
variable's value is '!' or '-n'.  It's only if it's unset, empty, or
contains characters from $IFS that a problem occurs.  Some other OSes
(*cough* Solaris *cough*) have versions of /bin/sh that can choke on
those, but OpenBSD's follows the rules there.)


> +If you are not intentionally trying to evaluate multiple elements in a
list,
> +you can avoid these caveats if you use
> +.Dq if \&[\&[ -z $foo \&]\&]
> +for testing zero length, and use
> +.Dq if \&[\&[ -n $foo \&]\&]
> +for testing non-zero length. As noted above, the use of
> +.Dq if \&[\&[ $foo \&]\&]
> +is not valid, so you'll need to use the
> +.Sq Fl n
> +operator.

While directing people to use [[...]] might be okay for the ksh(1)
manpage, it won't fly for the sh(1) manpage.  Simply saying "quote
your arguments!" on both would be simpler.


Philip Guenther

Reply via email to