Date: Sun, 12 Oct 2014 06:55:52 -0500 From: "William A. Mahaffey III" <wam@hiwaay.net> Cc: freebsd-questions@freebsd.org Subject: Re: sh man page .... Message-ID: <543A6C48.1010304@hiwaay.net> In-Reply-To: <20141012201841.P56328@sola.nimnet.asn.au> References: <mailman.59.1413028801.77252.freebsd-questions@freebsd.org> <20141012201841.P56328@sola.nimnet.asn.au>
next in thread | previous in thread | raw e-mail | index | archive | help
On 10/12/14 05:34, Ian Smith wrote: > Re: freebsd-questions Digest, Vol 540, Issue 6, Message: 7 > On Fri, 10 Oct 2014 10:41:49 -0500 "William A. Mahaffey III" <wam@hiwaay.net> wrote: > > On 10/10/14 10:30, Michael Sierchio wrote: > > > On Fri, Oct 10, 2014 at 8:30 AM, William A. Mahaffey III <wam@hiwaay.net> wrote: > > > > > >> .....I had a bunch of shell scripts written to use Linux > > >> sh, which was in fact bash, which means it had a superset of the arithmetic > > >> operators that traditional sh had. When I use these scripts under sh under > > >> FBSD 9.3, they largely work, though there are some minor differences (empty > > >> strings evaluate to zero (0) under bash, error under sh). The man page for > > >> sh doesn't reflect some of these compatibilities/incompatibilities, > > > Nor should it. The Bourne Shell is the Bourne Shell, is adequately > > > documented by the man page, and warnings about incompatibility are the > > > responsibility of those who foist off bash as sh. > > > > > > You're blaming your own bad habit on others. :-) > > > Well !!!! The sh man page is mute on the fact that an empty string is an > > error in arithmetic or logical evaluations, which is an omission > > irrespective of what bash does :-). > > No, sh(1) sayeth regarding $((...)), removing some whitespace: > > The allowed expressions are a subset of C expressions, summarized below. > Values All values are of type intmax_t. > Constants Decimal, octal (starting with 0) and hexadecimal (start- > ing with 0x) integer constants. > Variables Shell variables can be read and written and contain > integer constants. > Unary operators > ! ~ + - > Binary operators > * / % + - << >> < <= > >= == != & ^ | && || > Assignment operators > = += -= *= /= %= <<= >>= &= ^= |= > Conditional operator > ? : > The result of the expression is substituted in decimal. > > Now unary operations require a single value; binary operations, two. > > Undefined variables resolve to "", so expressions become invalid where > one (for unary) or for binary, either|both arguments are null|undefined. > > > I presume that converting Linux users to FBSD users is an agenda item > > here (maybe my error), > > Not really; sh(1) is the standard, and we're not chasing 'converts' like > it were some kind of religion - clearly there's more than enough of that > in the world! bash claims to be sh compatible and I've always taken it > at its word by using nothing but sh syntax in bash scripts on Debian :) > > > thus suitably complete man pages should be an important goal, I would > > think. I didn't think converting from Linux to FBSD was/is a bad > > habit ;-) .... > > Noone would argue that completeness is a goal, and while mentioning that > sh DOES NOT convert undefined (or null) variables to 0 - which is pretty > weird - is therefore unnecessary, this brings up one thing that should > be mentioned, and I'll do so below in response to RW's post. > > bash(1) specifically states: "A shell variable that is null or unset > evaluates to 0 when referenced by name without using the parameter > expansion syntax." and later "A null value evaluates to 0", but it goes > without saying - because it's not said - that in sh(1) that is not so. > > I'll also point out that bash(1) is 5463 lines (on 9.3) and sh(1) is > 1631 lines, or just less than 30% the size. From bash(1): > > BUGS > It's too big and too slow. > > There are some subtle differences between bash and traditional versions > of sh, mostly because of the POSIX specification. > > 'subtle differences' hardly cuts it, and to reverse the onus, bash(1) > doesn't point out ITS incompatible foibles - like this very 0 thing. > > In Message: 12 > On Fri, 10 Oct 2014 18:38:14 +0100 RW <rwmaillists@googlemail.com> wrote:: > > On Fri, 10 Oct 2014 10:30:19 -0500 > > William A. Mahaffey III wrote: > [..] > > > I have a FBSD 9.3 desktop that supplanted a Linux FC14 desktop used > > > for web access, some light development, & other day-to-day tasks > > > (i.e. my daily driver, so to speak). I had a bunch of shell scripts > > > written to use Linux sh, which was in fact bash, which means it had a > > > superset of the arithmetic operators that traditional sh had. When I > > > use these scripts under sh under FBSD 9.3, they largely work, though > > > there are some minor differences (empty strings evaluate to zero (0) > > > under bash, error under sh). > > > > Can you give an example? > > > > $ sh > > $ echo $((1+c)) > > 1 > > Now this is strange. bash(1) points out that "Within an expression, > shell variables may also be referenced by name without using the > parameter expansion syntax". That this works in sh(1) does appear to be > undocumented, though I've quite often seen it used, and wondered. And > what's worse, when you DO use the full form ($variable), it fails! > > % sh -c 'echo $(( 1+c ))' > 1 > % sh -c 'echo $(( 1-c ))' > 1 > % sh -c 'echo $(( 1/c ))' > arithmetic expression: division by zero: " 1/c " > % sh -c 'echo $(( 1|c ))' > 1 > % sh -c 'echo $(( 1&c ))' > 0 > > But: > > % sh -c 'echo $(( 1 & $c ))' > arithmetic expression: expecting primary: " 1 & " > % sh -c 'echo $(( 1 ^ $c ))' > arithmetic expression: expecting primary: " 1 ^ " > % sh -c 'echo $(( 1 + $c ))' > arithmetic expression: expecting primary: " 1 + " > % sh -c 'echo $(( 1 + c ))' > 1 > > As far as I can tell, neither of these behaviours are documented, though > I may have missed something; sh(1) is generally both terse and precise. > > And further [just _sometimes_ quoting from digests can be useful :-] > > > Straight out of the script which is failing. Under linux, if I call the > > script w/ no '-s #' option, the variable 'slept' is not set, & linux (or > > more accurately linux bash) evaluates that to the value oif zero (0). > > > > > > [wam@kabini1, ~, 7:07:22pm] 386 % sh > > $ if [ 0 -lt $(($slept)) ] ; then echo -n "$cmd: sleeping $slept secs > > ...." ; sleep $(($slept)) ; echo " done." ; fi > > arithmetic expression: expecting primary: "" > > [wam@kabini1, ~, 7:07:45pm] 387 % > > So just precede that and similar instances with: > > [ -z "$slept" ] && slept=0 # or [ ! "$slept" ] ... > > Either way, quotes are required around potentially undef/null variables > in test aka [, and never hurt. > > And though it's only what I read in sh(1), you should be able to use the > ${parameter:=word} form to assign a default value if unset or null: > > if [ 0 -lt ${slept:=0} ; ... # no need for the $((..)) form > > cheers, Ian > 100% correct on all facts, & I agree 100% w/ everything you say/said .... including the point that some of the behaviors are undocumented, & possibly unexpected (my assessment) .... That's all I was (lamely) asking for, a bit more detail in the sh man page :-) .... The references to bash by me were for context *only* .... Thx for the detailed & illuminating reply. -- William A. Mahaffey III ---------------------------------------------------------------------- "The M1 Garand is without doubt the finest implement of war ever devised by man." -- Gen. George S. Patton Jr.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?543A6C48.1010304>