sh man page ....
William A. Mahaffey III
wam at hiwaay.net
Sun Oct 12 11:49:46 UTC 2014
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 at 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 at 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 at 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 at 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 at 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.
More information about the freebsd-questions
mailing list