shellcheck
shellcheck copied to clipboard
SC2124 warns even for single-element array range assignments.
#!/bin/bash
a=(1 2 3 4)
f=${a[@]:1:1}
: "$f"
The above warns about SC2124 on the f
assignment but that assignment is selecting a set of elements of length 1.
Out of curiosity, did this come up in real code?
It came up in code I actually wrote. How "real" that code is you can judge for yourself. =)
https://github.com/deryni/expandTilde.sh/blob/master/tildeExpand.sh#L36
Looking at it again there's no reason not to just use *
there instead but @
is my default as it is almost universally more useful.
And actually, looking at this again I notice that when run on the tests.sh
file in that repository SC2088 only triggers on the three lines with ~
by itself and not the other lines where ~
is used for other expansions. (And I did just find a comment about people not using the ~user/
uses in another filed issue and while I generally agree with you it is actually useful in very specific situations. We've found some for it at work recently.)
this has come up in Google with people trying to slice off the last element:
config="${@: -1}"
technically the lint warning is incorrect here, although from a style pov, i can see people arguing that you should stick to $*
to be consistent and avoid further confusing people who aren't great with shell code.
here's some test data:
#!/bin/bash
# should warn
var="${@}"
var="${@: -2}"
var="${@: -2:2}"
var="${@:1}"
var="${@:1:2}"
var="${@:2:-2}"
var="${@:$i}"
var="${@:1:$i}"
# arguably should not warn
var="${@: -1}"
var="${@: -1:1}"
var="${@: -2:1}"
var="${@:1:1}"
var="${@:2:-1}"
# pathological
var="${@:1:0}"
# silence unused warnings
export var
i can't think of a scenario off the top of my head where a count of 0
would make sense.
I would argue that it should warn.
${@:1:1}
is not a single element. It's between 0 and 1 elements, inclusive.
${*:1:1}
, meanwhile, is exactly 1 element. If the parameter is undefined, it's the empty string.
It might warrant a separate warning explaining this though. This would additionally allow you to disable it if you're so inclined.
when it comes to variable assignment, the distinction doesn't matter. but when it comes to arguments, it does, although shellcheck doesn't flag this.
#!/bin/bash
set --
[ "${@:2:1}" = "a" ]
this suffers from under quoting and it really should be "${*:2:1}" for that reason.
Even worse, ${var[index]}
and ${var[@]:index:1}
are not synonyms even for assignment.
It turns out that ${var:start:length}
has a surprising quirk:
x=(alpha bravo charlie delta)
unset 'x[1]'
y="${x[1]}"
z="${x[@]:1:1}"
echo "${y:-Yvoid}" "${z:-Zvoid}"
You might expect Yvoid Zvoid
, but no, the output is Yvoid charlie
.