On Mon, 11 Jan 2010 13:13:44 -0800 Philip Guenther <guent...@gmail.com> wrote:
> 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. > Ah, good to know. Thanks. The reason I went out of my way to specifically test NULL is due to the wording in the standard. # http://www.opengroup.org/onlinepubs/9699919799/utilities/test.html # # string # True if the string string is not the null string; otherwise, false The wording for the ksh(1) man page says ``[ string ]'' tests for non-zero length, so this gets into how NULL is defined... --until one learns they've been stripped. ;-) > > > 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 ]] > Agreed. I also thought the above addition was was over-kill. > > +.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 , > ) > Thanks. > > 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... > Yep. We'd have an endless man page. > Then again, 'test' does seem to be the place where people first slam > into this. <mumble> > I resemble that remark. :-) > (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.) > On OpenBSD, with ``test ...'' and ``[...]'' the behavior of unary operators stored within an operand makes sense, but only if you think it through completely to realize the field separation of operand strings exists to *ENABLE* you to stuff other operators or operands into the test. On the other hand, if you don't think it through completely, even OpenBSD will fail to follow the principal of least surprise (but it's your fault) when an operand string contains an unary operator followed by an IFS. --Just another example supporting your statement below about adding a, "Quote your arguments!" line to the ksh and sh man pages. Perhaps a more accurate description like, "unary followed by IFS" would be better? I'm still trying to fully understand the behavior of strings containing a newline <sigh> and I need to poke at it a bit more, but I think having at least some mention of behavior of tests when operands contain a newline is an improvement. > > > +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. > Excellent Point! The more provocative question is, "Why would you want field splitting of operands in the [...] tests?" Yes, I know the field splitting exists so you can feed various operators and operands into the test, but I have a hunch the [[...]] syntax was added to ksh specifically because someone noticed the field splitting stuff typically does more harm than good if you're not thinking it through. Of course, using the ksh [[...]] feature makes scripts less portable between shells, so quoting operands is a better answer. Do you think the addition of the [[...]] syntax in ksh was due to misunderstanding of field splitting (failure to quote), prevention of less than easy to understand syntax like: ``[ -o foo -o -o !foo ]'' # From the ksh man page. and similar? I'll try to cook up a better diff tomorrow in light of what you said above. Philip (and also kili@), thanks for your help over the last couple weeks with the ksh stuff. I've been trying to find at least a rough answer to the impossible question of, "What makes a shell good?" -- J.C. Roberts