$@ 数组与常规数组有何不同

How is the $@ array different from regular array

我写了一个函数来检查参数是否传递给了脚本,所以我必须为 $@ 创建一个别名变量,因为在函数内部它将是函数的参数。 这是代码:

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}"
}

虽然我绝对想了解如何更短地实施它,但这不是我的问题的主题(尽管一些建议将不胜感激;])。

我的问题与 for passed_arg in ${script_args}; do 行有关:

为什么当 script_args 在字符串内展开时它不起作用,即 "${script_args}",而 "${@}""$@" 却起作用。 只有 ${script_args} 有效。

那么 $@ 与常规数组(如 (a b c))有何不同,script_args$@ 有何不同? 有什么收获?

$@ 不是数组,虽然它类似于数组。

赋值 script_args=$@ 只是创建一个常规参数,其值是 $@ 的内容与 space 连接而成。如果你真的想要一个具有相同内容的array,使用

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}"
}

这种包含检查也可以使用关联数组来完成(只要参数不是空字符串)。

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
}
    

根据您对它们的比较方式,它们没有什么不同,因为与位置参数非常相似的数组用引号扩展:"${script_args[@]}"

此外,您存储的参数有误。使用 script_args=$@ 可以将字符串值存储到 script_args。该值是 $@ 的值与用作连词的 space 的合并形式。

要将它们存储为数组,请使用 script_name=("$@")。阅读 Bash 手册的 Arrays 部分以了解更多信息。