f



Expansion of ${var+something "$var"} if $var is empty

Suppose you have a variable whose content you want to pass to a
sub-process as argument to an option but only if that variable
is set.

Rather than

  if test -n "${var+1}"; then
    cmd -x "$var"
  else
    cmd
  fi

I thought that

  cmd ${var+-x "$var"}

would do the trick. Turns out that with most shells, it doesn't
if $var is set but empty.

- Dash 0.5.7 expands ��${var+something "$var"}�� to two words
  containing "something" and the value of $var respectively,
  which is what I wanted.

- Ksh 93u+ omits the second word if $var is empty.

- Bash 4.3.30 follows Ksh, on purpose or by accident.

- Zsh 5.0.7 expands it to one word : "something $var".

Haven't mustered the energy to dig into the standard to see
which behaviours are compliant but I'm certainly curious.

-- 
Andr� Majorel http://www.teaser.fr/~amajorel/
"Pauvret� n'est pas vice ! Parbleu ! Un vice est agr�able."
  -- _Passe-temps_
0
Andre
12/16/2016 12:26:38 PM
comp.unix.shell 15484 articles. 2 followers. Post Follow

32 Replies
293 Views

Similar Articles

[PageSpeed] 12

On 16.12.2016 13:26, Andre Majorel wrote:
> Suppose you have a variable whose content you want to pass to a
> sub-process as argument to an option but only if that variable
> is set.
> 
> Rather than
> 
>   if test -n "${var+1}"; then
>     cmd -x "$var"
>   else
>     cmd
>   fi
> 
> I thought that
> 
>   cmd ${var+-x "$var"}
> 
> would do the trick. Turns out that with most shells, it doesn't
> if $var is set but empty.
> 
> - Dash 0.5.7 expands � ${var+something "$var"} � to two words
>   containing "something" and the value of $var respectively,
>   which is what I wanted.
> 
> - Ksh 93u+ omits the second word if $var is empty.

Just to be sure; you say that ksh omits the second = _empty_ word?

But this seems not to be true. If you quote your outer expression

  cmd "${var+-x "$var"}"

you will see that ksh expands it to '-x ' (i.e. '-x <empty>'). But
in case of

  cmd ${var+-x "$var"}

the final space is removed before it's passed to cmd, since the
expression is unquoted. To me this looks pretty much like standard
behaviour.

Janis

> 
> - Bash 4.3.30 follows Ksh, on purpose or by accident.
> 
> - Zsh 5.0.7 expands it to one word : "something $var".
> 
> Haven't mustered the energy to dig into the standard to see
> which behaviours are compliant but I'm certainly curious.
> 

0
Janis
12/16/2016 1:03:44 PM
On 16.12.2016 14:03, Janis Papanagnou wrote:
> On 16.12.2016 13:26, Andre Majorel wrote:
>> Suppose you have a variable whose content you want to pass to a
>> sub-process as argument to an option but only if that variable
>> is set.
>>
>> Rather than
>>
>>   if test -n "${var+1}"; then
>>     cmd -x "$var"
>>   else
>>     cmd
>>   fi
>>
>> I thought that
>>
>>   cmd ${var+-x "$var"}
>>
>> would do the trick. Turns out that with most shells, it doesn't
>> if $var is set but empty.
>>
>> - Dash 0.5.7 expands � ${var+something "$var"} � to two words
>>   containing "something" and the value of $var respectively,
>>   which is what I wanted.
>>
>> - Ksh 93u+ omits the second word if $var is empty.
> 
> Just to be sure; you say that ksh omits the second = _empty_ word?
> 
> But this seems not to be true. If you quote your outer expression
> 
>   cmd "${var+-x "$var"}"
> 
> you will see that ksh expands it to '-x ' (i.e. '-x <empty>'). But
> in case of
> 
>   cmd ${var+-x "$var"}
> 
> the final space is removed before it's passed to cmd, since the
> expression is unquoted. To me this looks pretty much like standard
> behaviour.

PS (just in case it's not obvious from what I've written above):
If you want the second argument to be there in any case, and also
want to separate the option from the argument to pass to cmd, you
can add single quotes around $var, as in

  cmd ${var+-x "'$var'"}

You will get consistent output with ksh, bash, dash (and can
likely let zsh behave that way as well with appropriate settings).

Janis

>>
>> - Bash 4.3.30 follows Ksh, on purpose or by accident.
>>
>> - Zsh 5.0.7 expands it to one word : "something $var".
>>
>> Haven't mustered the energy to dig into the standard to see
>> which behaviours are compliant but I'm certainly curious.
>>
> 

0
Janis
12/16/2016 1:51:03 PM
On Friday, 16 December 2016 17:56:42 UTC+5:30, Andre Majorel  wrote:
> 
> Suppose you have a variable whose content you want to pass to a
> sub-process as argument to an option but only if that variable
> is set.
> 
> Rather than
> 
>   if test -n "${var+1}"; then
>     cmd -x "$var"
>   else
>     cmd
>   fi
> 

> 
> I thought that
> 
>   cmd ${var+-x "$var"}
> 
> would do the trick. Turns out that with most shells, it doesn't
> if $var is set but empty.
> 


  This would do the trick
        cmd ${var:+-x "$var"}

Note the : before the +
0
Rakesh
12/16/2016 7:07:19 PM
On Fri, 16 Dec 2016 11:07:19 -0800, Rakesh Sharma wrote:

>   This would do the trick
>         cmd ${var:+-x "$var"}
> 
> Note the : before the +

Could you please give more notes on this solution?

Regards
-- 
..: Hongyi Zhao [ hongyi.zhao AT gmail.com ] Free as in Freedom :.
0
Hongyi
12/17/2016 12:07:18 PM
Andre Majorel <cheney@halliburton.com>:
> Suppose you have a variable whose content you want to pass to a
> sub-process as argument to an option but only if that variable
> is set.
>
> Rather than
>
>   if test -n "${var+1}"; then
>     cmd -x "$var"
>   else
>     cmd
>   fi

cmd ${var+"-x"} ${var+"$var"}

will run

cmd -x "$var"

if var is set.  Otherwise, it will run

cmd
0
Helmut
12/17/2016 2:46:18 PM
On Saturday, 17 December 2016 20:16:33 UTC+5:30, Helmut Waitzmann  wrote:

> 
> cmd ${var+"-x"} ${var+"$var"}
> 
> will run
> 
> cmd -x "$var"
> 
> if var is set.  Otherwise, it will run
> 
> cmd
> 

Just remember that a var can be set AND null. In that scenario 
   cmd -x ''
will happen. This is not what the OP wanted. This is somewhat subtle,
that cmd sees 2 arguments, '-x' and an empty argument ''.

The solution to this is the :+ 
meaning
  ${VAR:+alternate_value} => use the alternate value only when VAR is set AND nonnull
otherwise replace everything with a null.
Now this `otherwise' comprises cases of a variable that is set BUT null || a variable is not set.

HTH
0
Rakesh
12/17/2016 9:57:42 PM
On Sat, 17 Dec 2016 13:57:42 -0800, Rakesh Sharma wrote:

> Just remember that a var can be set AND null. In that scenario
>    cmd -x ''
> will happen. This is not what the OP wanted. This is somewhat subtle,
> that cmd sees 2 arguments, '-x' and an empty argument ''.

What's the meaning of -x here?

Regards
-- 
..: Hongyi Zhao [ hongyi.zhao AT gmail.com ] Free as in Freedom :.
0
Hongyi
12/17/2016 11:55:22 PM
On Sunday, 18 December 2016 05:25:24 UTC+5:30, Hongyi Zhao  wrote:

> 
> What's the meaning of -x here?
> 

Nothing. It could be anything for that matter.

0
Rakesh
12/18/2016 12:06:36 AM
Hongyi Zhao wrote:

> On Sat, 17 Dec 2016 13:57:42 -0800, Rakesh Sharma wrote:
>> Just remember that a var can be set AND null. In that scenario
>>    cmd -x ''
>> will happen. This is not what the OP wanted. This is somewhat subtle,
>> that cmd sees 2 arguments, '-x' and an empty argument ''.
> 
> What's the meaning of -x here?

Placeholder for an option argument.

-- 
PointedEars

Twitter: @PointedEars2
Please do not cc me. / Bitte keine Kopien per E-Mail.
0
Thomas
12/18/2016 12:08:06 AM
Rakesh Sharma <sharma__r@hotmail.com>:
> On Saturday, 17 December 2016 20:16:33 UTC+5:30, Helmut Waitzmann  wrote:
>
>>=20
>> cmd ${var+"-x"} ${var+"$var"}
>>=20
>> will run
>>=20
>> cmd -x "$var"
>>=20
>> if var is set.  Otherwise, it will run
>>=20
>> cmd
>>=20
>
> Just remember that a var can be set AND null. In that scenario=20
>    cmd -x ''
> will happen.=20

That's correct.  And if I understand the OP correctly, that is,
what he wants.  He wrote:

  Suppose you have a variable whose content you want to pass to a
  sub-process as argument to an option but only if that variable
  is set.

In his statement, there is nothing about =E2=80=9Conly if that variable
set and not null=E2=80=9D.

> This is not what the OP wanted.

As far as I understad the OP, he wished to achieve the semantics
of the following =E2=80=9Cif=E2=80=9D command.  He wrote:

  Rather than

    if test -n "${var+1}"; then
      cmd -x "$var"
    else
      cmd
    fi

The condition of the =E2=80=9Cif=E2=80=9D statement will be true iff the va=
riable
=E2=80=9Cvar=E2=80=9D is set, not regarding whether null or not.

And then he hoped to get those same semantics using a more compact
syntax:

  I thought that

    cmd ${var+-x "$var"}

  would do the trick.=20

But then he learned, that this is not the case with most shells:

  Turns out that with most shells, it doesn't if $var is set but
  empty.

  - Dash 0.5.7 expands =C2=AB=C2=A0${var+something "$var"}=C2=A0=C2=BB to t=
wo words
    containing "something" and the value of $var respectively,
    which is what I wanted.

That is, he blesses Dash's behaviour and puts it in opposition to
some different shells:

  - Ksh 93u+ omits the second word if $var is empty.

Apparently he wishes, that Ksh wouldn't omit an empty $var.

  - Bash 4.3.30 follows Ksh, on purpose or by accident.

  - Zsh 5.0.7 expands it to one word : "something $var".

Apparently he wishes, that Zsh wouldn't join the two words into
one.
0
Helmut
12/20/2016 1:59:13 AM
On Tuesday, 20 December 2016 20:54:02 UTC+5:30, Helmut Waitzmann  wrote:

>=20
> In his statement, there is nothing about =E2=80=9Conly if that variable
> set and not null=E2=80=9D.
>=20

No, the OP does mention about the set variable being null...

>[OP]  I thought that=20
>[OP]      cmd ${var+-x "$var"}=20
>[OP]  would do the trick. Turns out that with most shells, it doesn't=20
>[OP]  if $var is set but empty.=20
0
Rakesh
12/21/2016 11:02:11 AM
On 2016-12-20, Helmut Waitzmann <nn.throttle@xoxy.net> wrote:
> Rakesh Sharma <sharma__r@hotmail.com>:
>> On Saturday, 17 December 2016 20:16:33 UTC+5:30, Helmut Waitzmann  wrote:
>>
>>> 
>>> cmd ${var+"-x"} ${var+"$var"}
>>> 
>>> will run
>>> 
>>> cmd -x "$var"
>>> 
>>> if var is set.  Otherwise, it will run
>>> 
>>> cmd
>>> 
>>
>> Just remember that a var can be set AND null. In that scenario 
>>    cmd -x ''
>> will happen.
>
> That's correct.  And if I understand the OP correctly, that is,
> what he wants.  He wrote:
>
>   Suppose you have a variable whose content you want to pass to a
>   sub-process as argument to an option but only if that variable
>   is set.
>
> In his statement, there is nothing about ???only if that variable
> set and not null???.

Right. I wrote "is set" and that is what I meant. Had I wanted
the semantics of ${:+}, the phrasing would have included
"non-empty" or something like that.

>> This is not what the OP wanted.
>
> As far as I understad the OP, he wished to achieve the semantics
> of the following ???if??? command.  He wrote:
>
>   Rather than
>
>     if test -n "${var+1}"; then
>       cmd -x "$var"
>     else
>       cmd
>     fi
>
> The condition of the ???if??? statement will be true iff the variable
> ???var??? is set, not regarding whether null or not.
>
> And then he hoped to get those same semantics using a more compact
> syntax:
>
>   I thought that
>
>     cmd ${var+-x "$var"}
>
>   would do the trick. 
>
> But then he learned, that this is not the case with most shells:
>
>   Turns out that with most shells, it doesn't if $var is set but
>   empty.
>
>   - Dash 0.5.7 expands ��${var+something "$var"}�� to two words
>     containing "something" and the value of $var respectively,
>     which is what I wanted.
>
> That is, he blesses Dash's behaviour and puts it in opposition to
> some different shells:
>
>   - Ksh 93u+ omits the second word if $var is empty.
>
> Apparently he wishes, that Ksh wouldn't omit an empty $var.
>
>   - Bash 4.3.30 follows Ksh, on purpose or by accident.
>
>   - Zsh 5.0.7 expands it to one word : "something $var".
>
> Apparently he wishes, that Zsh wouldn't join the two words into
> one.

Right again.

To my surprise, your syntax does get the desired result with
Dash, Bash and Zsh. Ksh persists in omitting the second word
(the one where the value of $var goes), though.

No idea why a shell would expand

  ${var+-x} ${var+"$var"}

differently from

  ${var+-x "$var"}

but Bash and Zsh do. Well played.

The Ksh exception doesn't bother me so much because I don't know
of any platforms where a script beginning with "#!/bin/sh" would
be executed by Ksh. I'd like to know whether the ��${var+-x}
${var+"$var"}�� syntax works in other Bourne and POSIX shells,
however.

-- 
Andr� Majorel http://www.teaser.fr/~amajorel/
"Pauvret� n'est pas vice ! Parbleu ! Un vice est agr�able."
  -- _Passe-temps_
0
Andre
12/21/2016 2:27:45 PM
On 2016-12-16, Janis Papanagnou <janis_papanagnou@hotmail.com> wrote:
> On 16.12.2016 14:03, Janis Papanagnou wrote:
>> On 16.12.2016 13:26, Andre Majorel wrote:
>>> Suppose you have a variable whose content you want to pass to a
>>> sub-process as argument to an option but only if that variable
>>> is set.
>>>
>>> Rather than
>>>
>>>   if test -n "${var+1}"; then
>>>     cmd -x "$var"
>>>   else
>>>     cmd
>>>   fi
>>>
>>> I thought that
>>>
>>>   cmd ${var+-x "$var"}
>>>
>>> would do the trick. Turns out that with most shells, it doesn't
>>> if $var is set but empty.
>>>
>>> - Dash 0.5.7 expands � ${var+something "$var"} � to two words
>>>   containing "something" and the value of $var respectively,
>>>   which is what I wanted.
>>>
>>> - Ksh 93u+ omits the second word if $var is empty.
>> 
>> Just to be sure; you say that ksh omits the second = _empty_ word?

Yes.

>> But this seems not to be true. If you quote your outer expression
>> 
>>   cmd "${var+-x "$var"}"
>> 
>> you will see that ksh expands it to '-x ' (i.e. '-x <empty>').

Ah yes, but then the expression would be expanded into one word,
which is not the objective.

>> But in case of
>> 
>>   cmd ${var+-x "$var"}
>> 
>> the final space is removed before it's passed to cmd, since the
>> expression is unquoted. To me this looks pretty much like standard
>> behaviour.

Does that means that Dash's behaviour is non-standard, then ?

> PS (just in case it's not obvious from what I've written above):
> If you want the second argument to be there in any case, and also
> want to separate the option from the argument to pass to cmd, you
> can add single quotes around $var, as in
>
>   cmd ${var+-x "'$var'"}
>
> You will get consistent output with ksh, bash, dash (and can
> likely let zsh behave that way as well with appropriate settings).

This gives consistent results with Dash, Bash and Ksh but not
useful ones (the inverted commas end up in argv[]).

-- 
Andr� Majorel http://www.teaser.fr/~amajorel/
"Pauvret� n'est pas vice ! Parbleu ! Un vice est agr�able."
  -- _Passe-temps_
0
Andre
12/21/2016 2:41:35 PM
On 21.12.2016 15:41, Andre Majorel wrote:
[...]
> This gives consistent results with Dash, Bash and Ksh but not
> useful ones (the inverted commas end up in argv[]).

Ah, yes, you're right.

I suppose it's probably best to use Helmut's suggestion - but
in quoted form! - to keep the args (specifically the second
one) together and also take an empty argument as an empty field
instead of removing it

  cmd "${var+"-x"}" "${var+"$var"}"


Janis

0
Janis
12/21/2016 4:35:54 PM
On 21.12.2016 15:27, Andre Majorel wrote:
[...]
> 
> The Ksh exception doesn't bother me so much because I don't know
> of any platforms where a script beginning with "#!/bin/sh" would
> be executed by Ksh.

What about AIX ?

Janis

0
Janis
12/21/2016 4:37:48 PM
Andre Majorel wrote:

> On 2016-12-16, Janis Papanagnou <janis_papanagnou@hotmail.com> wrote:
>> On 16.12.2016 14:03, Janis Papanagnou wrote:
>>> On 16.12.2016 13:26, Andre Majorel wrote:
>>>> […]
>>>> I thought that
>>>>
>>>>   cmd ${var+-x "$var"}
>>>>
>>>> would do the trick. Turns out that with most shells, it doesn't
>>>> if $var is set but empty.
>>>>
>>>> - Dash 0.5.7 expands « ${var+something "$var"} » to two words
>>>>   containing "something" and the value of $var respectively,
>>>>   which is what I wanted.
>>>>
>>>> - Ksh 93u+ omits the second word if $var is empty.
>>> 
>>> Just to be sure; you say that ksh omits the second = _empty_ word?
> 
> Yes.
> 
> […]
>>> But in case of
>>> 
>>>   cmd ${var+-x "$var"}
>>> 
>>> the final space is removed before it's passed to cmd,

Which “final space” are you referring to?

>>> since the expression is unquoted. To me this looks pretty much like 
>>> standard behaviour.
> 
> Does that means that Dash's behaviour is non-standard, then ?

According to POSIX.1-2008 chapter “2. Shell Command Language”, section 
“2.6.2 Parameter Expansion” [1],

  ${parameter+word}

shall be substituted with “word” if “parameter” is “Set But Null” (whereas 
the standard uses “null” and “Null” to mean the string of length zero, 
presumably because then the NUL character would be the value in C).

AIUI this means that

   ${var+something "$var"}

shall be substituted with

  something "$var"

if “var” is “Set But Null”.

The standard also says:

| If a parameter expansion occurs inside double-quotes:
| 
|   * Pathname expansion shall not be performed on the results of the 
|     expansion.
| 
|   * Field splitting shall not be performed on the results of the 
|     expansion.

From which we can assume that if parameter expansion does _not_ occur inside 
double-quotes (so without quotes, as single-quotes would prevent expansion 
altogether), both pathname expansion and field splitting shall be performed. 
This is also substantiated by

| 2.6.5 Field Splitting
| 
| After parameter expansion (Parameter Expansion), […] the shell shall scan
| the results of expansions and substitutions that did not occur in double-
| quotes for field splitting and multiple fields can result.
| 
| The shell shall treat each character of the IFS as a delimiter and use the 
| delimiters as field terminators to split the results of parameter 
| expansion, command substitution, and arithmetic expansion into fields.
 
There are no pathnames, and field splitting with the default $IFS value 
would leave

  'something' "$var"

Since “$var” is syntactically a parameter reference, and parameter expansion 
is _not_ one of the forms of expansion that “shall not be performed on the 
results of the expansion” if it “occurs inside double-quotes”, the shell 
then shall perform parameter expansion again, substituting the above with

  'something' ""

because “If the parameter is not enclosed in braces, and is a name, the 
expansion shall use the longest valid name (see XBD Name), whether or not 
the variable represented by that name exists” and “The value, if any, of 
‘parameter’ shall be substituted”, the empty string shall be substituted.

So ISTM that there should be two words according to the standard, one non-
empty and one empty, and as dash is doing that – test code:

  (x=''; printf '"%s"\n' ${x+-x "$x"})

–, it is standards-compliant there while the shells that do not are not.

[1] 
<http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02>
 
-- 
PointedEars

Twitter: @PointedEars2
Please do not cc me. / Bitte keine Kopien per E-Mail.
0
Thomas
12/21/2016 7:51:32 PM
On Wednesday, 21 December 2016 19:57:48 UTC+5:30, Andre Majorel  wrote:

>=20
> The Ksh exception doesn't bother me so much because I don't know
> of any platforms where a script beginning with "#!/bin/sh" would
> be executed by Ksh. I'd like to know whether the =C2=AB=C2=A0${var+-x}
> ${var+"$var"}=C2=A0=C2=BB syntax works in other Bourne and POSIX shells,
> however.
>=20

I misunderstood the requirements of the OP, i.e. you, completely.=20
Helmut's suggestion is the perfect workaround for the issue at hand.

What I'd like to point out is that the shell only expands into space-separa=
ted
words when the argument is a "$@"
that is, ${var+"$@"} =3D> will yield multiple words even if some be empty

set -- '-x' "${var-}"
cmd ${var+"$@"}
0
Rakesh
12/21/2016 11:34:59 PM
Andre Majorel <cheney@halliburton.com>:
> On 2016-12-20, Helmut Waitzmann <nn.throttle@xoxy.net> wrote:

[Citing the OP:]

>>   - Dash 0.5.7 expands =C2=AB=C2=A0${var+something "$var"}=C2=A0=C2=BB t=
o two words
>>     containing "something" and the value of $var respectively,
>>     which is what I wanted.

> To my surprise, your syntax=20

[ ${var+-x} ${var+"$var"} ]

> does get the desired result with Dash, Bash and Zsh. Ksh
> persists in omitting the second word (the one where the value of
> $var goes), though.

Just to be sure:  What does Ksh print, if given the command line

var=3D'' ; printf '>%s<\n' ${var+-x} ${var+"$var"}

to it?

> I'd like to know whether the =C2=AB=C2=A0${var+-x} ${var+"$var"}=C2=A0=C2=
=BB syntax
> works in other Bourne and POSIX shells, however.

As Thomas pointed out, at least in POSIX shells it should work.

I'm not sure, whether POSIX mandates, that

=E2=80=9C${var+-x "$var"}=E2=80=9D

shall be the same as

=E2=80=9C${var+-x} ${var+"$var"}=E2=80=9D, though.
0
Helmut
12/22/2016 1:47:58 AM
On Thursday, 22 December 2016 05:05:05 UTC+5:30, Rakesh Sharma  wrote:

> 
> set -- '-x' "${var-}"
> cmd ${var+"$@"}
> 

Actually the following:
  set -- "${var-}"
  cmd ${var+-x "$@"}
0
Rakesh
12/22/2016 1:48:46 AM
On Friday, 16 December 2016 17:56:42 UTC+5:30, Andre Majorel  wrote:

> 
> Suppose you have a variable whose content you want to pass to a
> sub-process as argument to an option but only if that variable
> is set.
> 

> 
>   cmd ${var+-x "$var"}
> 
> would do the trick. Turns out that with most shells, it doesn't
> if $var is set but empty.
> 

The answer to this is provided by the posix shell manual:

****
If the complete expansion appropriate for a word results in an empty field, that empty field shall be deleted from the list of fields that form the completely expanded command, unless the original word contained single-quote or double-quote characters.
****

http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02
0
Rakesh
12/22/2016 6:25:17 AM
Janis Papanagnou <janis_papanagnou@hotmail.com> wrote:
> On 21.12.2016 15:27, Andre Majorel wrote:
> [...]
>> 
>> The Ksh exception doesn't bother me so much because I don't know
>> of any platforms where a script beginning with "#!/bin/sh" would
>> be executed by Ksh.
> 
> What about AIX ?

Also Solaris (ksh93) and OpenBSD (pdksh).
0
william
12/22/2016 7:39:02 AM
On 2016-12-22, <william@wilbur.25thandClement.com> wrote:
> Janis Papanagnou <janis_papanagnou@hotmail.com> wrote:
>> On 21.12.2016 15:27, Andre Majorel wrote:
>> [...]
>>> 
>>> The Ksh exception doesn't bother me so much because I don't know
>>> of any platforms where a script beginning with "#!/bin/sh" would
>>> be executed by Ksh.
>> 
>> What about AIX ?

Are you asking me or telling me ?

If the former, I can't recall, it's been too long.

> Also Solaris (ksh93) and OpenBSD (pdksh).

Are you saying that Solaris and OpenBSD symlink /bin/sh to some
flavour of Ksh ?

Don't know about OpenBSD but IME, Solaris comes with a very old
pre-POSIX /bin/sh which couldn't possibly pass for Ksh.

-- 
Andr� Majorel http://www.teaser.fr/~amajorel/
"Pauvret� n'est pas vice ! Parbleu ! Un vice est agr�able."
  -- _Passe-temps_
0
Andre
12/22/2016 10:59:59 AM
Andre Majorel <cheney@halliburton.com> writes:

>Are you saying that Solaris and OpenBSD symlink /bin/sh to some
>flavour of Ksh ?

True in Solaris 11/11 (2011) and later.

>Don't know about OpenBSD but IME, Solaris comes with a very old
>pre-POSIX /bin/sh which couldn't possibly pass for Ksh.

That is the case in Solaris 10 (2005) and earlier.

Casper
0
Casper
12/22/2016 11:32:24 AM
On 2016-12-22, Helmut Waitzmann <nn.throttle@xoxy.net> wrote:
> Andre Majorel <cheney@halliburton.com>:
>> On 2016-12-20, Helmut Waitzmann <nn.throttle@xoxy.net> wrote:
>
> [Citing the OP:]
>
>>>   - Dash 0.5.7 expands ��${var+something "$var"}�� to two words
>>>     containing "something" and the value of $var respectively,
>>>     which is what I wanted.
>
>> To my surprise, your syntax 
>
> [ ${var+-x} ${var+"$var"} ]
>
>> does get the desired result with Dash, Bash and Zsh. Ksh
>> persists in omitting the second word (the one where the value of
>> $var goes), though.
>
> Just to be sure:  What does Ksh print, if given the command line
>
> var='' ; printf '>%s<\n' ${var+-x} ${var+"$var"}
>
> to it?

With Debian's ksh 93u+20120801
$ ksh <<\EOF
var='' ; printf '>%s<\n' ${var+-x} ${var+"$var"}
EOF
>-x<

Since william@ mentioned pdksh, I tried the nearest thing in
Debian, MirBSD Ksh 50d-5 and had some luck :

$ mksh <<\EOF
var='' ; printf '>%s<\n' ${var+-x} ${var+"$var"}
EOF
>-x<
><

Bash 4.3.30, Dash 0.5.7, mksh 50d, Posh 0.12.3 and Zsh 5.0.7 all
get the same results. The odd man out is Ksh 93u+20120801.

You can make Ksh produce an empty argument by following Janis'
recommendation and putting double quotation marks around the
second word as in either of the following :

  ${var+-x} "${var+"$var"}"
  ${var+-x} "${var+$var}"

But that has the undesirable side-effet of creating an empty
argument when the variable is unset.

So far, we don't have any syntax that works in all cases and on
all shells.

>> I'd like to know whether the ��${var+-x} ${var+"$var"}�� syntax
>> works in other Bourne and POSIX shells, however.
>
> As Thomas pointed out, at least in POSIX shells it should work.
>
> I'm not sure, whether POSIX mandates, that
>
> ???${var+-x "$var"}???
>
> shall be the same as
>
> ???${var+-x} ${var+"$var"}???, though.

-- 
Andr� Majorel http://www.teaser.fr/~amajorel/
"Pauvret� n'est pas vice ! Parbleu ! Un vice est agr�able."
  -- _Passe-temps_
0
Andre
12/22/2016 11:47:19 AM
On Thursday, 22 December 2016 17:17:22 UTC+5:30, Andre Majorel  wrote:

> 
> So far, we don't have any syntax that works in all cases and on
> all shells.
> 

You may try this on your various shells (I don't have access to them all):

        set 'X' '-x' "${var-}"; shift; cmd ${var+"$@"}
0
Rakesh
12/22/2016 1:18:17 PM
On 22.12.2016 11:59, Andre Majorel wrote:
>> Janis Papanagnou <janis_papanagnou@hotmail.com> wrote:
>>> On 21.12.2016 15:27, Andre Majorel wrote:
>>> [...]
>>>>
>>>> The Ksh exception doesn't bother me so much because I don't know
>>>> of any platforms where a script beginning with "#!/bin/sh" would
>>>> be executed by Ksh.
>>>
>>> What about AIX ?
> 
> Are you asking me or telling me ?

It was meant as a hint. Since I assumed you may have missed it given the
impression I got from your statement ("I don't know of any platforms")
that you have inspected the common (including commercial) Unix platforms
which you obviously didn't. Sorry, that this question mark was confusing.

> 
> If the former, I can't recall, it's been too long.

I do recall, and it had been the case at least until AIX 4.x. (Don't know
about current AIX'es; but why should they change that? [just a rhetorical
question here])

Janis

> [...]


0
Janis
12/22/2016 5:07:13 PM
Andre Majorel wrote:

> The Ksh exception doesn't bother me so much because I don't know
> of any platforms where a script beginning with "#!/bin/sh" would
> be executed by Ksh.

http://www.in-ulm.de/~mascheck/various/shells/ tries to break down
that in detail. But it does not try to judge age, market share,
and alike, just collecting the very information.
0
Sven
12/22/2016 8:27:08 PM
Andre Majorel <cheney@halliburton.com> wrote:
> On 2016-12-22, <william@wilbur.25thandClement.com> wrote:
>> Janis Papanagnou <janis_papanagnou@hotmail.com> wrote:
>>> On 21.12.2016 15:27, Andre Majorel wrote:
>>> [...]
>>>> 
>>>> The Ksh exception doesn't bother me so much because I don't know
>>>> of any platforms where a script beginning with "#!/bin/sh" would
>>>> be executed by Ksh.
>>> 
>>> What about AIX ?
> 
> Are you asking me or telling me ?

That was Janis Papanagnou, not me.
 
> If the former, I can't recall, it's been too long.

/bin/sh on AIX is ksh88

  $ uname -a
  AIX aix7 1 7 000ACFDE4C00
  $ cmp /bin/sh /bin/ksh; echo RC=$?
  RC=0

>> Also Solaris (ksh93) and OpenBSD (pdksh).
> 
> Are you saying that Solaris and OpenBSD symlink /bin/sh to some
> flavour of Ksh ?

Yes, except OpenBSD uses a hardlink.

> Don't know about OpenBSD but IME, Solaris comes with a very old
> pre-POSIX /bin/sh which couldn't possibly pass for Ksh.

That changed 5 years ago with Solaris 11

  solaris-11-3:~$ ls -go /bin/sh
  lrwxrwxrwx   1      11 Aug 16 15:39 /bin/sh -> amd64/ksh93

See https://blogs.oracle.com/OTNGarage/entry/new_shell_in_oracle_solaris
0
william
12/22/2016 9:47:03 PM
In article <585bb9c8$0$21513$e4fe514c@news.xs4all.nl>,
Casper H.S. Dik  <Casper.Dik@OrSPaMcle.COM> wrote:
>Andre Majorel <cheney@halliburton.com> writes:
>
>>Are you saying that Solaris and OpenBSD symlink /bin/sh to some
>>flavour of Ksh ?
>
>True in Solaris 11/11 (2011) and later.
>
>>Don't know about OpenBSD but IME, Solaris comes with a very old
>>pre-POSIX /bin/sh which couldn't possibly pass for Ksh.
>
>That is the case in Solaris 10 (2005) and earlier.

Well, Solaris now comes with ksh93 installed as /bin/sh and given that ksh93 is 
not POSIX compliant, the effect is pretty much the same:

-	You cannot expect a POSIX shell under /bin/sh

-	POSIX even does not require /bin/sh to be POSIX compliant.

-	PATH=`getconf PATH`
	sh
	gives you a POSIX shell and this is why #!/bin/sh in a script
	does not grant you a POSIX shell.

AFAIK, the latter method still gives you a POSIX shell - even under Solaris 11, 
but I am not sure whether the POSIX shell you get on Solaris has been updated 
to follow recent changes and fixes in POSIX.

Ksh93 is mainly POSIX compliant (so it is closer to the POSIX standard than the 
SVr4 Bourne Shell used by Solaris 10), but some of the builtins do not create 
the right output and some commands that must be implemented as builtins to work 
as documented are just aliases in ksh93.

Note that the POSIX shell on Solaris is based on ksh88 but differs from ksh88 
as even a vanilla ksh88 is not POSIX compliant. The behavior of the Solaris 
enhanced ksh88 is however frequently used by the POSIX commitee when 
investigating in shell behavior.

Because of all these problems, the OpenSolaris based SchilliX uses an enhanced 
and expected to be POSIX compliant version of the Bourne Shell as /bin/sh, 
called "bosh". See:

	http://schilytools.sourceforge.net/bosh.html

In general the idea used on recent Linux distros is not that bad:

-	use a mainly POSIX compliant shell as /bin/sh

-	Avoid kshisms and bashisms in system srcipts this way.

Unfortunately, the shell usually used as /bin/sh on Linux (dash) does not 
implement support for multi-byte locales. This way, you can certify Linux only 
for "embedded use", as a full blown POSIX platform is expected to support "XSI" 
enhancements. BTW: "bosh" has been verified to work on Gentoo Linux when 
installed as /bin/sh.

-- 
EMail:joerg@schily.net			(home) J�rg Schilling D-13353 Berlin
   joerg.schilling@fokus.fraunhofer.de (work) Blog: http://schily.blogspot.com/
URL: http://cdrecord.org/private/ http://sf.net/projects/schilytools/files/
0
Joerg
12/23/2016 9:49:58 AM
On 23.12.2016 10:49, Joerg.Schilling@fokus.fraunhofer.de wrote:
> [...]
> 
> Ksh93 is mainly POSIX compliant (so it is closer to the POSIX standard than the 
> SVr4 Bourne Shell used by Solaris 10), but some of the builtins do not create 
> the right output and some commands that must be implemented as builtins to work 
> as documented are just aliases in ksh93.

("just aliases"? - I suppose you don't mean aliases to builtins like
fc/hist/history; or what would the issue be here? - Other predefined
aliases seem to refer to ksh-specific commands, mostly typeset's, so
I'd say there shouldn't be a relation to POSIX anyway in those cases.)

Mind to be more specific on each of those points you mentioned, and
elaborate on why it's non-POSIX, please?

Janis

> 
> [...]

0
Janis
12/23/2016 6:17:32 PM
On 2016-12-22, Andre Majorel <cheney@halliburton.com> wrote:

>> Also Solaris (ksh93) and OpenBSD (pdksh).
>
> Are you saying that Solaris and OpenBSD symlink /bin/sh to some
> flavour of Ksh ?

OpenBSD's /bin/sh is (by now a somewhat modified) pdksh and has
been for twenty years.  I think it also behaves slightly different
depending on whether it is called as sh or ksh, but that's already
a level of detail that is of little practical interest in a world
where too many people expect /bin/sh to be bash or, alternatively,
/bin/bash to be universally available.

-- 
Christian "naddy" Weisgerber                          naddy@mips.inka.de
0
Christian
12/23/2016 6:20:08 PM
Joerg.Schilling@fokus.fraunhofer.de wrote:
<snip>
> Note that the POSIX shell on Solaris is based on ksh88 but differs from ksh88 
> as even a vanilla ksh88 is not POSIX compliant. The behavior of the Solaris 
> enhanced ksh88 is however frequently used by the POSIX commitee when 
> investigating in shell behavior.

I didn't realize Solaris had a ksh88 variant. Cool. I guess I should have
read the manual closer.

I've encountered these two particularly annoying ksh88 bugs that required
workarounds:

  # trap EXIT) ksh88 (confirmed AIX 7.1) wrongly executes an EXIT trap when
  #   the calling function returns, rather than when the shell exits. Note
  #   ksh93 does not exhibit this bug.
  #
  # $@ and null IFS) ksh88 (confirmed AIX 7.1) pdksh (confirmed pdksh 5.2.14)
  #   and pdksh derivatives (confirmed OpenBSD 5.6 ksh, NetBSD 6.1 ksh) will
  #   expand $@ as a single field if IFS is null (set but empty). As a
  #   workaround we set IFS to a control character when juggling paths. ksh93,
  #   bash, and ash correctly expand $@ when IFS is null.

Testing /usr/xpg4/bin/sh on Solaris 11.3 (which the manual says is ksh88 +
POSIX corrections), only the former is fixed. The latter issue remains. The
script

  null_ifs() {
    IFS=
    set -- "$@"
    printf "\$# -> %d\n" $#
  }
  null_ifs 1 2 3

produces

  $# -> 1

instead of

  $# -> 3

It's a shame because it's possible to walk and juggle paths with embedded
whitespace (including newlines) using POSIX shell semantics. It's not even
that tricky as long as you can reliably disable field splitting and rely on
positional parameters in lieu of arrays.[1] Every native (/bin/sh) shell
I've tested gets it right except for the ksh88 derivatives. ksh93 might be
less standard's compliant, but not all deviations are equal.

[1] The latter--the ability to use positional parameters--probably isn't
strictly necessary. Once or twice I've implemented "arrays" using serially
incremented global names. But supporting 8-bit clean paths in my scripts is
mostly an intellectual exercise on my part. Without the ability to easily
pass lists of filenames to internal functions, it's not worth the bother to
accomodate broken implementations. Thus the hack of using a control
character.[2]

[2] Interestingly, bash chokes on \1 as a field separator, producing wierd
results. That's why I use \2 in the following routine for printing the
string value for "null" IFS.

  # see porting note "$@ and null IFS"
  null_ifs() {
    IFS=
    set -- x y z
    set -- "$@"
    unset IFS
    [ $# -gt 1 ] || printf "\2"
  }

That code will evaluate to the empty string for bash because it can handle a
null IFS properly, but I didn't want to forget about that quirk of bash.
0
william
12/23/2016 10:16:19 PM
Reply: