[bash 4] 'test -v 1' is never true

2022-11-25 Thread Alejandro Colomar

Hi!

I wrote a script, and am trying it on many systems.  On RHEL8, which has bash 4, 
it didn't work.  I could reduce the problem to the following command, which 
never returns true:


test -v 1;

In Debian Sid, where I develop, and where I have bash 5, that works fine, and is 
true if the function or script in which it is has any arguments.  On zsh(1) it 
also works fine.


Is this a known bug in bash?
The exact version where I can reproduce it is 4.4.20(1)-release 
(x86_64-redhat-linux-gnu).


Cheers,

Alex


--



OpenPGP_signature
Description: OpenPGP digital signature


Re: [bash 4] 'test -v 1' is never true

2022-11-25 Thread Alejandro Colomar

Hi Branden!

On 11/25/22 22:40, G. Branden Robinson wrote:

Hi Alex,

At 2022-11-25T22:02:46+0100, Alejandro Colomar wrote:

I wrote a script, and am trying it on many systems.  On RHEL8, which
has bash 4, it didn't work.  I could reduce the problem to the
following command, which never returns true:

 test -v 1;

In Debian Sid, where I develop, and where I have bash 5, that works
fine, and is true if the function or script in which it is has any
arguments.  On zsh(1) it also works fine.

Is this a known bug in bash?
The exact version where I can reproduce it is 4.4.20(1)-release
(x86_64-redhat-linux-gnu).


I don't think it is a bug.  It is unspecified behavior according to
POSIX.

"-v" is not an operator according to POSIX,


Yeah, I know.  I tried dash(1), which at least gives some warning:

$ cat bug.sh
#!/bin/bash

echo $1;

test -v 1 \
&& echo 'arguments';

$ dash bug.sh

bug.sh: 5: test: -v: unexpected operator



and I don't recall seeing it
in any shell.  It is therefore interpreted as a string argument.


But `-v` is a specified option of bash(1) (and also, at least, zsh(1)):

$ help test | grep '\-v'
  -v VAR True if the shell variable VAR is set.


I find it very useful, since I use `set -Eeufo pipefail` in my scripts, to 
simplify error handling.  When I want to use a variable that might be undefined, 
I first check if it exists.




   The algorithm for determining the precedence of the operators and the
   return value that shall be generated is based on the number of
   arguments presented to test. (However, when using the "[...]" form,
   the right-bracket final argument shall not be counted in this
   algorithm.)

   In the following list, $1, $2, $3, and $4 represent the arguments
   presented to test:

   0 arguments:
   Exit false (1).
   1 argument:
   Exit true (0) if $1 is not null; otherwise, exit false.
   2 arguments:

   If $1 is '!', exit true if $2 is null, false if $2 is not
   null.

   If $1 is a unary primary, exit true if the unary test is true,
   false if the unary test is false.

   Otherwise, produce unspecified results.

https://pubs.opengroup.org/onlinepubs/009695299/utilities/test.html

Regards,
Branden


Cheers,

Alex

--
<http://www.alejandro-colomar.es/>


OpenPGP_signature
Description: OpenPGP digital signature


Re: [bash 4] 'test -v 1' is never true

2022-11-26 Thread Alejandro Colomar

Hi Chet!

On 11/26/22 18:44, Chet Ramey wrote:

On 11/25/22 4:02 PM, Alejandro Colomar wrote:

Hi!

I wrote a script, and am trying it on many systems.  On RHEL8, which has bash 
4, it didn't work.  I could reduce the problem to the following command, which 
never returns true:


 test -v 1;


This is a bash feature. I cribbed it from ksh93, and it first appeared in
bash-4.2.

The initial implementation was restricted to shell variables -- positional
parameters like $1 are not shell variables.

After a bunch of requests, like

https://lists.gnu.org/archive/html/bug-bash/2018-12/msg00098.html
https://lists.gnu.org/archive/html/bug-bash/2018-12/msg00104.html
https://lists.gnu.org/archive/html/bug-bash/2020-01/msg00027.html

I added support for testing positional parameters in bash-5.1.


That was my gut; thanks!  I'll workaround with $#.

Cheers,

Alex


--
<http://www.alejandro-colomar.es/>


OpenPGP_signature
Description: OpenPGP digital signature


Re: [bash 4] 'test -v 1' is never true

2022-11-27 Thread Alejandro Colomar

Hi Alexey,

On 11/27/22 12:41, Alexey wrote:

On 2022-11-26 21:45, Alejandro Colomar wrote:

That was my gut; thanks!  I'll workaround with $#.


I could suggest you to use for clarity another construction:
[[ ${1+isset} ]] || echo "not set"

Here "isset" is just for readability. You could place any other string literal 
there.


I actually find that very confusing.  What feature is it using?  I couldn't find 
it with `info bash | less` then `/\+`.


test $# -ge 1

has the benefit that it's just a sed(1) away from my old

test -v 1

And it only needs the following to be understood:

man test | grep -A1 ' -ge '
man sh | grep '   # '

The old version (test -v 1) required:

help test | grep ' -v '
man sh | sed -n '/^   Positional/,/^$/p'

Both are easy to find.



Regards,
Alexey.


Cheers,

Alex

--
<http://www.alejandro-colomar.es/>


OpenPGP_signature
Description: OpenPGP digital signature


Re: [bash 4] 'test -v 1' is never true

2022-11-27 Thread Alejandro Colomar



On 11/27/22 14:10, David wrote:

On Mon, 28 Nov 2022 at 00:01, Alejandro Colomar  wrote:

On 11/27/22 12:41, Alexey wrote:

On 2022-11-26 21:45, Alejandro Colomar wrote:



I could suggest you to use for clarity another construction:
[[ ${1+isset} ]] || echo "not set"



Here "isset" is just for readability. You could place any other string literal
there.



I actually find that very confusing.  What feature is it using?  I couldn't find
it with `info bash | less` then `/\+`.


See:
https://www.gnu.org/software/bash/manual/bash.html#Shell-Parameter-Expansion
- Under heading: ${parameter:+word}
- The parameter is 1
- The word is isset
- The colon ':' is optional, explained by the sentences beginning with
"Omitting the colon" ..


Ahh, it was the optional-ness of ':' that bugged me.  I'm also quite 
unaccustomed to [[ expr ]].  :)


Thanks!

Cheers,

Alex


--
<http://www.alejandro-colomar.es/>


OpenPGP_signature
Description: OpenPGP digital signature