Re: Empty ""s in ARG in ${x:+ARG} expand to no words instead of the empty word if prepended/appended with space

2018-07-21 Thread Robert Elz
Date:Sat, 21 Jul 2018 11:33:18 -0400
From:Chet Ramey 
Message-ID:  <2fe93203-93fd-2a97-ff54-7cb748294...@case.edu>

  | Even if the whitespace gets stripped out, the quoted null string should
  | result in an empty argument.

Yes, it certainly should (and unless IFS has been set "oddly"
the white space will be removed, but that's irrelevant).

For what it is worth, as recently as 4.2.0 (and maybe more recently)
bash got this right, so it is something that has changed in 4.3 or 4.4
(or maybe later in 4.2).

kre




Re: Empty ""s in ARG in ${x:+ARG} expand to no words instead of the empty word if prepended/appended with space

2018-07-21 Thread Bob Proulx
Chet Ramey wrote:
> Bob Proulx wrote:
> > Denys Vlasenko wrote:
> >> $ f() { for i; do echo "|$i|"; done; }
> >> $ x=x
> >> $ e=
> >> $ f ${x:+ ""}
> >> ^^^ prints nothing, bug?
> >>
> >> $  ${x:+"" }
> >> ^^^ prints nothing, bug?
> > 
> > Insufficient quoting.  That argument should be quoted to avoid the
> > whitespace getting stripped.  (Is that during word splitting phase
> > using the IFS?  I think so.)
> 
> Even if the whitespace gets stripped out, the quoted null string should
> result in an empty argument. Different shells are inconsistent about this,
> but I believe that if word splitting occurs, the empty string (or "$e",
> anything that expands to an empty string) should result in a null word.

Gotcha.  Thanks!

And further testing confirms the inconsistent shells.  bash and ksh
both seem to be the outliers in different ways in terms of behavior.
dash and zsh seem to be consistent and correct in this.

Bob



Re: Empty ""s in ARG in ${x:+ARG} expand to no words instead of the empty word if prepended/appended with space

2018-07-21 Thread Chet Ramey
On 7/21/18 12:44 AM, Bob Proulx wrote:
> Denys Vlasenko wrote:
>> $ f() { for i; do echo "|$i|"; done; }
>> $ x=x
>> $ e=
>> $ f ${x:+ ""}
>> ^^^ prints nothing, bug?
>>
>> $  ${x:+"" }
>> ^^^ prints nothing, bug?
> 
> Insufficient quoting.  That argument should be quoted to avoid the
> whitespace getting stripped.  (Is that during word splitting phase
> using the IFS?  I think so.)

Even if the whitespace gets stripped out, the quoted null string should
result in an empty argument. Different shells are inconsistent about this,
but I believe that if word splitting occurs, the empty string (or "$e",
anything that expands to an empty string) should result in a null word.

-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/



Re: Empty ""s in ARG in ${x:+ARG} expand to no words instead of the empty word if prepended/appended with space

2018-07-21 Thread Chet Ramey
On 7/20/18 10:43 AM, Denys Vlasenko wrote:
> $ f() { for i; do echo "|$i|"; done; }
> $ x=x
> $ e=

Thanks for the report. I'll take a look at what needs to be done here.


-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/



Re: Empty ""s in ARG in ${x:+ARG} expand to no words instead of the empty word if prepended/appended with space

2018-07-21 Thread Ilkka Virta

On 21.7. 07:44, Bob Proulx wrote:

Denys Vlasenko wrote:

$ f() { for i; do echo "|$i|"; done; }
$ x=x
$ e=
$ f ${x:+ ""}
^^^ prints nothing, bug?

$  ${x:+"" }
^^^ prints nothing, bug?


Insufficient quoting.  That argument should be quoted to avoid the
whitespace getting stripped.  (Is that during word splitting phase
using the IFS?  I think so.)

Try this:

   f "${x:+ ""}"
   f "${x:+"" }"


That's not the same at all. With outer quotes, the result will always be 
a single word. Without them, having an empty 'x' would result in no word:



Without outer quotes:

$ for cond in "" "1" ; do for value in "" "*" ; do printf "<%s>\t" 
"$cond" "$value" ${cond:+"$value"}; echo; done; done

<>  <>
<>  <*>
<1> <>  <>
<1> <*> <*>


With outer quotes:

$ for cond in "" "1" ; do for value in "" "*" ; do printf "<%s>\t" 
"$cond" "$value" "${cond:+"$value"}"; echo; done; done

<>  <>  <>
<>  <*> <>
<1> <>  <>
<1> <*> <*>


I suppose that could be used to pass optional arguments to some command.

Though different shells do behave a bit differently here, and I'm not 
sure which behaviour is the correct one. With the values from the third 
line in the above test (the other three seem consistent), different shells:



No extra spaces in ${cond:+"$value"}:

$ for shell in bash dash ksh "zsh -y" ; do $shell -c 'cond=1; value=""; 
printf "<%s> " "$0" ${cond:+"$value"}; echo;' ; done

 <>
 <>

 <>


Extra spaces in ${cond:+ "$value" }:

$ for shell in bash dash ksh "zsh -y" ; do $shell -c 'cond=1; value=""; 
printf "<%s> " "$0" ${cond:+ "$value" }; echo;' ; done


 <>
 <>
 <>


Or with multiple words inside:

$ for shell in bash dash ksh "zsh -y" ; do $shell -c 'cond=1; printf 
"<%s> " "$0" ${cond:+"" "x" ""}; echo;' ; done

 
 <>  <>
 <> 
 <>  <>


It doesn't seem like a very good idea to rely on this, arrays would of 
course work better.



Bash: GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)
ksh:version sh (AT Research) 93u+ 2012-08-01
zsh:  zsh 5.3.1 (x86_64-debian-linux-gnu)
dash: Debian's 0.5.8-2.4


--
Ilkka Virta / itvi...@iki.fi



Re: Empty ""s in ARG in ${x:+ARG} expand to no words instead of the empty word if prepended/appended with space

2018-07-20 Thread Bob Proulx
Denys Vlasenko wrote:
> $ f() { for i; do echo "|$i|"; done; }
> $ x=x
> $ e=
> $ f ${x:+ ""}
> ^^^ prints nothing, bug?
> 
> $  ${x:+"" }
> ^^^ prints nothing, bug?

Insufficient quoting.  That argument should be quoted to avoid the
whitespace getting stripped.  (Is that during word splitting phase
using the IFS?  I think so.)

Try this:

  f "${x:+ ""}"
  f "${x:+"" }"

Also in the future please say what version of bash you are using.
There have been a lot of bugs fixed in various versions.

Bob



Re: Empty ""s in ARG in ${x:+ARG} expand to no words instead of the empty word if prepended/appended with space

2018-07-20 Thread Denys Vlasenko

On 07/20/2018 04:43 PM, Denys Vlasenko wrote:

$  ${x:+"" }
^^^ prints nothing, bug?


Should be:
$ f ${x:+"" }


$ f ${x:+"$e""$e"""}
^^^ prints nothing, bug?


Should be:
$ f ${x:+"$e""$e" ""}

sorry.