I wrote a function to check whether argument(s) was passed to script, so I had to create an alias variable for $@ because inside function that would be function's arguments.
Here's the code:
script_args=$@
is_arg_passed() {
local passed=false
for passed_arg in ${script_args}; do
for arg in "$@"; do
if [[ "${passed_arg}" == "${arg}" ]]; then
passed=true
break
fi
done
[[ "${passed}" == true ]] && break
done
echo "${passed}"
}
Though I definitely would like to learn how it can be implemented shorter, that's not the topic of my question (though some advice would be appreciated ;]).
My question is related to the for passed_arg in ${script_args}; do line:
Why does it not work when script_args expanded within string i.e. "${script_args}", when "${@}" or "$@" does.
Only ${script_args} works.
So how is $@ different from the regular array (like (a b c)), and how is script_args different from $@?
What is the catch?
CodePudding user response:
$@ is not an array, though it is array-like.
The assignment script_args=$@ simply creates a regular parameter whose value is the contents of $@ concatenated with a space. If you really want an array with the same contents, use
script_args=( "$@" ) # The quotes are critical!
is_arg_passed() {
local passed=false
for passed_arg in "${script_args[@]}"; do # So are these quotes!
for arg in "$@"; do
if [[ "${passed_arg}" == "${arg}" ]]; then
passed=true
break
fi
done
[[ "${passed}" == true ]] && break
done
echo "${passed}"
}
This kind of containment check can also be done using an associative array (as long as the arguments are not empty strings).
declare -A script_args
for arg; do
# The value doesn't matter; we'll only be checking
# if the key exists.
script_args["$arg"]=
done
is_arg_passed() {
for arg; do
if ! [[ -v script_args[$arg] ]]; then
echo false
return 1
fi
done
echo true
return 0
}
CodePudding user response:
They're not different based on how you compare them because an array much like the positional parameters is expanded with a quote: "${script_args[@]}"
Also you're storing the arguments wrong. With script_args=$@ you store a string value to script_args. The value is a merged form of the values of $@ with the space used as a conjunctor.
To store them as an array, use script_name=("$@"). Read the Arrays section of the Bash manual to know more about it.
