Search code examples
bashshellzsh

How is the $@ array different from regular array


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?


Solution

  • 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.