On 19/04/2023 08:46, wwp wrote:> Hello lejeczek, > > > On Wed, 19 Apr 2023 08:10:16 +0200 lejeczek <peljasz at yahoo.co.uk> wrote: > >> On 19/04/2023 08:04, wwp wrote: >>> Hello lejeczek, >>> >>> >>> On Wed, 19 Apr 2023 07:50:29 +0200 lejeczek via CentOS <centos at centos.org> wrote: >>> >>>> Hi guys. >>>> >>>> I cannot wrap my hear around this: >>>> >>>> -> $ unset _Val; test -z ${_Val}; echo $? >>>> 0 >>>> -> $ unset _Val; test -n ${_Val}; echo $? >>>> 0 >>>> -> $ _Val=some; test -n ${_Val}; echo $? >>>> 0 >>>> >>>> What is this!? >>>> How should two different, opposite tests give the same result >>>> Is there some bash option which affects that and if so, then what would be the purpose of such nonsense? >>> Surround ${_Val} with double quotes (as you should) and things will be different: >>> >>> $ unset _Val; test -n "${_Val}"; echo $? >>> 1 >>> >>> Now you get it? :-) >>> >>> >> I don't know, am not sure, I remembered it differently, did not think enclosing quotes were necessary(always?) for that were {} > {} does not prevent this (at least not in bash): > > $ FOO="a b" > > $ test -z $FOO > bash: test: a: binary operator expected > > $ test -z ${FOO} > bash: test: a: binary operator expected > > Because after $FOO or ${FOO} variable expansion, bash parsed: > test -z a b > 'b' is unexpected, from a grammar point of view. > > Quoting is expected, here: > $ test -z "$FOO" > <no error> > > When FOO is unset, apparently it's a different matter, where you end up > with $?=0 in all unquoted -n/-z cases, interestingly. I could not find > this specific case in the bash documentation. That may not be portable > to other shells, BTW. I only use {} when necessary (because of what > bash allows to do between {}, plenty!, or when inserting $FOO into a > literal string that may lead the parser to take the whole string for a > variable name: echo $FOObar != echo ${FOO}bar). > > > Regards,There is a several ways to run tests in shell, but 'test' which is own binary as I understand, defeats me.. in those three examples - regardless of how one can "bend" quoting & expanding - the same identical variable syntax is used and yet different tests render the same result. I thought 'test' broke and I had remembered it differently - meaning 'test' used to give results I thought it did - or perhaps some 'shopt' changed and affected its behavior. I'd expect a consistency, like with what I usually do to test for empty var: -> $ export _Val=some; [[ -v _Val ]]; echo $? 0 -> $ unset _Val; [[ -v _Val ]]; echo $? 1 Learning, re-learning, round & round it goes.. thanks, L.
Once upon a time, lejeczek <peljasz at yahoo.co.uk> said:> There is a several ways to run tests in shell, but 'test' which is > own binary as I understand, defeats me.. > in those three examples - regardless of how one can "bend" quoting & > expanding - the same identical variable syntax is used and yet > different tests render the same result.It's because shell variable expansion happens before the command is run. When you do: unset _Val; test -z ${_Val} The shell expands ${_Val} to nothing, then does whitespace removal, and runs test with a single argument, "-z". When instead you do: unset _Val; test -z "${_Val}" The shell sees the quoted string and keeps it as an empty argument, so test gets run with two arguments: "-z", and "" (null aka a zero-length string). It appears that test treats -z/-n (and other tests) with no following argument as always successful, rather than an error. Checking the POSIX/Single Unix Specification standard, this is compliant; it says that any time test is run with one argument, the exit is true (0) if the argument is not null, false otherwise (e.g. test "" is false, while test -blob is true). Note that bash has test and [ as shell builtins, but the external command /usr/bin/test and /usr/bin/[ have the same behavior. The [[ ]] method is a bash extension, and treats a test operator without a corresponding operand (e.g. [[ -z ]]) as an error condition instead of returning true. -- Chris Adams <linux at cmadams.net>
On Wed, Apr 19, 2023 at 09:16:26PM +0200, lejeczek via CentOS wrote:>On 19/04/2023 08:46, wwp wrote: >> Hello lejeczek,...>>>> Surround ${_Val} with double quotes (as you should) and things will be different: >>>> >>>> $ unset _Val; test -n "${_Val}"; echo $? >>>> 1 >>>> >>>> Now you get it? :-) >>>> >>> I don't know, am not sure, I remembered it differently, did not think enclosing quotes were necessary(always?) for that were {} >> {} does not prevent this (at least not in bash): >> >> $ FOO="a b" >> >> $ test -z $FOO >> bash: test: a: binary operator expected >> >> $ test -z ${FOO} >> bash: test: a: binary operator expected >> >> Because after $FOO or ${FOO} variable expansion, bash parsed: >> test -z a b >> 'b' is unexpected, from a grammar point of view. >> >> Quoting is expected, here: >> $ test -z "$FOO" >> <no error> >> >> When FOO is unset, apparently it's a different matter, where you end up >> with $?=0 in all unquoted -n/-z cases, interestingly. I could not find >> this specific case in the bash documentation. That may not be portable >> to other shells, BTW. I only use {} when necessary (because of what >> bash allows to do between {}, plenty!, or when inserting $FOO into a >> literal string that may lead the parser to take the whole string for a >> variable name: echo $FOObar != echo ${FOO}bar). >> >> >> Regards, >There is a several ways to run tests in shell, but 'test' >which is own binary as I understand, defeats me..Yes, there is a binary for test (and its alternate '['). But most shells, including bash have incorporated code for test (and other commands) into the shell code itself for efficiency. $ type test test is a shell builtin> >I'd expect a consistency, like with what I usually do to >test for empty var: >-> $ export _Val=some; [[ -v _Val ]]; echo $? >0 >-> $ unset _Val; [[ -v _Val ]]; echo $? >1 >I do hope you don't use -v to test for empty variables as it tests for "set" variables and valid name syntax. Set variables can be "empty" ( name= ). But in your last example _Val is "un"set, it does not exist. Thus it can neither be empty nor occupied. -- Jon H. LaBadie jcu at labadie.us