- Double-quote your variables when you use them. Otherwise they'll break if you pass values that contain whitespace. Also, there's no need for that subshell. So instead of
if (usageSliceArr $1 $2 $3); then
you should write if usageSliceArr "$1" "$2" "$3"; then
- Use
-ne
to compare numbers, !=
for strings
- Don't forget there's https://shellcheck.net/
- Double-quote your variables when you use them
- Put the usage message inside the function that does the work, so that the code becomes self-documenting
- Write error messages to stderr rather than stdout
- Consider writing commands as shell scripts that live in your
$PATH
rather than functions available only if your ~/.bash_profile
is executed
- Did I mention you should double-quote your variables when you use them?
Here's one approach:
########################################################################
# slicearr name index count
#
# Return <count> space-separated and tokenised elements from the <name>
# array starting at <index>
#
slicearr() {
if [ $# -ne 3 ]
then
echo 'Usage: name index count' >&2
exit 1
fi
declare -n name=$1
printf "%s " "${name[@]:$2:$3}"; echo
}
The relevance of the space-separated and tokenised clause applies to your original code, too. Consider an array
a=( one two 'twenty three' )
The "twenty three" will be extracted as a single element but returned as two space-separated values "twenty" and "three".
IFS=$'\n'
doesn't remove the need to quote variables as as been said to you several times already. – Stéphane Chazelas Jun 29 '23 at 08:53-ne
than!=
which is a string comparison ([ "$#" -ne 3 ]
). – Stéphane Chazelas Jun 29 '23 at 08:55usageSliceArr $1 $2 $3
passes the first 3 provided arguments, subject to split+glob. You'd want to pass all the arguments withusageSliceArr "$@"
for your usage function to detect when the user passes more than 3. – Stéphane Chazelas Jun 29 '23 at 08:58(...)
is to spawn a subshell which in bash involves forking an extra process, so it's even more overhead. – Stéphane Chazelas Jun 29 '23 at 08:58$# != 3
covers both cases. – Nickotine Jun 29 '23 at 09:40if usageSliceArr "$@"; then
, there's no need to use a subshell. – Stéphane Chazelas Jun 29 '23 at 09:41if [ $# = 3 ]
is a bit like sayingif (the splitting of number of argument results in a string that is 3)
.if [ "$#" -eq 3 ]
isif (the number of arguments is 3)
. It's about using the correct syntax of the language. – Stéphane Chazelas Jun 29 '23 at 09:42((...))
? – Nickotine Jun 29 '23 at 09:45-eq
and=
– Nickotine Jun 29 '23 at 09:51-eq
vs=
if not about quotes? You're only comparing for equality and you know$#
is a properly formatted number so why not save keystrokes there, too and use=
? More to the point, comparing$#
with=
won't even cause a surprise breakdown in the user's face regardless of what they provide as input, while passing something containing an asterisk or spaces just well might if the value is used unquoted. And that's kinda the point there, doing the right thing to avoid issues in the future. – ilkkachu Jun 29 '23 at 19:14IFS=$'\n'
to stop word splitting. For*
I'll be careful when I son't want globbing but usually for wildcards I only want globbing. – Nickotine Jun 29 '23 at 19:16=
and other symbolic operators, you're right it doesn't make a difference, just that when it was pointed out that when you go deep those operators do string evaluation it jolted me although it works. I remember I used to use the letter operators then didn't do bash for a while and forgot them but I never forgot the symbolic operators. – Nickotine Jun 29 '23 at 19:24IFS=$'\n'
doesn't stop word splitting,IFS=
(setting the empty string) does. Yes, there's a difference, since the values your shell or shell functions get can contain newlines... Also neither does anything about stopping globbing, and stuff like*?[]
are also something that can appear in inputs. Relying on "there's never going to be glob chars" fails when you build a script that e.g. passes patterns tofind -name
, or something like that. Worst of all, all of those things can appear in filenames. Now, they hopefully won't, but they can, sadly. – ilkkachu Jun 29 '23 at 20:04find
functions I'll have to remember to setnoglob
for them, thanks for bringing that to my attention. I didn't say they stop globbing I just mean by being so loose I have learned about globbing and what to do about it. – Nickotine Jun 29 '23 at 20:11IFS=$'\n'
withbash -x
it comes up something likeIFS=$'
with the other quote on a newline (can't format that in the comments. Does this mean I haveIFS=''
and having\n
is doing nothing and could actually catch me out if something has a newline? – Nickotine Jun 29 '23 at 20:41set -x
output. So, what you see isIFS='<newline>'
. That's not the same as the empty string, orIFS=''
– ilkkachu Jun 30 '23 at 06:19