bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Bash test builtin fails on: test -n '>' -a 1 -eq 1


From: Chet Ramey
Subject: Re: Bash test builtin fails on: test -n '>' -a 1 -eq 1
Date: Tue, 22 Oct 2024 10:22:33 -0400
User-agent: Mozilla Thunderbird

On 10/22/24 3:34 AM, cirrus.mazurka-0t@icloud.com wrote:
The following produces a `bash: test: too many arguments` exception in `test`, 
with exit status 2:

``` bash
v='>'
test -n "$v" -a yes '!=' no # bash: test: too many arguments
echo $? # 2

test -n '>' -a 1 -eq 1 # bash: test: too many arguments
echo $? # 2

[ -n '>' -a 1 -eq 1 ] # bash: [: too many arguments
echo $? # 2

[[ -n '>' -a 1 -eq 1 ]]
# bash: syntax error in conditional expression
# bash: syntax error near `-a'
echo $? # 2
```

It works without the -a, and as such, it works using && instead of the -a:

```
v='>'
test -n "$v"
echo $? # 0

[ -n "$v" ]
echo $? # 0

test -n "$v" && test yes '!=' no
echo $? # 0

[ -n "$v" ] && [ yes '!=' no ]
echo $? # 0
```

There is no mention of this peculiar behaviour inside the documentation:
https://www.gnu.org/software/bash/manual/html_node/Bourne-Shell-Builtins.html#index-test

Since there are five or more arguments, bash parses and evaluates the
expression using the historical operator precedence algorithm instead of
the POSIX test algorithm, which works on the number of arguments. POSIX
leaves the behavior with 5 or more arguments unspecified, and removes the
-a and -o binary operators completely.

The historical algorithm gave binary operators like `>' greater precedence
than any of the unary operators.


Known versions affected:
GNU bash, version 5.2.37(1)-release (x86_64-apple-darwin22.6.0)
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin22)

If this is intended behaviour, then what is the suitable workaround?
1. Should I always use `&&` instead of `-a`?

Yes. The documentation for coreutils `test' already says this, POSIX says
the same thing, the current bash devel man page says

"The  historical operator-precedence parsing with 4 or more argu-
 ments can lead to ambiguities when it  encounters  strings  that
 look  like  primaries.  The POSIX standard has deprecated the -a
 and -o primaries and enclosing expressions  within  parentheses.
 Scripts  should  no longer use them.  It's much more reliable to
 restrict test invocations to a single primary,  and  to  replace
 uses of -a and -o with the shell's && and || list operators."

Plus it has the advantage of short-circuiting evaluation, which test does
not do.


2. Should I use a parameter replacement? e.g. `test -n "${v//>/.}" -a 1 -eq 1`

You shouldn't use -a to compose expressions at all.

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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]