Use "$@"
(incl. double quotes) in a list context to get a list of positional parameters, individually quoted.
Use "$*"
(incl. double quotes) in a scalar context to get the positional parameters concatenated into a single string with the first character of $IFS
(usually a space) as the delimiter.
Using $@
unquoted (as in your first example) or using "$@"
in a scalar context (as in your second example) rarely makes sense. In the bash
shell, using "$@"
in a scalar context is the same as using "$*"
with the first character of $IFS
set to a space.
When using snum=( "$@" )
, you create the array snum
. If you access the variable as $snum
, you will get the first element of the array. It is, in effect, the same as accessing ${snum[0]}
. Using "${snum[@]}"
gives you a list of the individually quoted elements, in a similar manner as "$@"
does. Using "${snum[*]}"
gives you the equivalent of "$*"
, but for the array snum
.
Assuming you want to create an array, snum
, from the list of positional parameters and then print that array if it's not empty, you may use
#!/bin/bash
snum=( "$@" )
if [ "${#snum[@]}" -gt 0 ]; then
printf '%s\n' "${snum[@]}"
fi
This prints the elements of snum
on separate lines if the script was given arguments.
Example run:
bash-5.1$ ./script 1 2 3 "hello world" 4
1
2
3
hello world
4
Notice that the hello world
argument is kept as a single argument, which would not be the case had you forgotten the quotes around $@
.
To print the list of positional parameters at a single string, delimited by colons. The colons are inserted between the positional parameters by modifying the $IFS
string.
#!/bin/bash
IFS=:
snum="$*"
if [ -n "$snum" ]; then
printf '%s\n' "$snum"
fi
The difference here is that snum
is now a single string, not an array of elements. The script outputs the string if it is non-empty, i.e., if the script was given at least one non-empty argument.
Or, modifying our first example only slightly to keep using snum
as an array,
#!/bin/bash
snum=( "$@" )
if [ "${#snum[@]}" -gt 0 ]; then
IFS=:
printf '%s\n' "${snum[*]}"
fi
Example run:
bash-5.1$ ./script 1 2 3 "hello world" 4
1:2:3:hello world:4