【问题标题】:How is the $@ array different from regular array$@ 数组与常规数组有何不同
【发布时间】:2022-01-04 16:38:42
【问题描述】:

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

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也不是。
  • @chepner 我只知道 bash 一天半,所以不太了解
  • @rowboat 的目的是检查是否存在任何给定的参数。感谢您提供信息,是的,我已经意识到最好从功能中使用return 状态。哇,zsh 方式很优雅

标签: bash shell zsh


【解决方案1】:

$@ 不是一个数组,尽管它类似于数组。

赋值script_args=$@ 只是创建一个常规参数,其值是$@ 的内容与空格连接。如果你真的想要一个具有相同内容的 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
}
    

【讨论】:

  • 谢谢!然后我还有两个问题:在这种情况下引用的作用是什么(我在 shellscripting 中绝对是菜鸟)?其次,这是什么for循环?它会自动使用$@ 吗?
  • 是的,for x; 等价于for x in "$@"。引号确保扩展产生的每个元素都是参数的完整值;未加引号的包含空格的元素本身将被视为多个元素。
  • 糟糕。 ${...} 是个脑残;我不知道我从未尝试使用空字符串作为数组键。
【解决方案2】:

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

而且你存储的参数是错误的。使用script_args=$@,您可以将字符串值存储到script_args。该值是$@ 的值与用作连接符的空格的合并形式。

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

【讨论】:

  • 谢谢!非常有用的信息。我还有一个问题:script_args=("$@") 中引号的作用是什么?在这种情况下,如果没有引号,结果会有所不同吗?此外,当我出于兴趣尝试script_args=("$@ x y z") 时,我得到了"a" "b" "c x y z"。这个怎么运作?对于像我这样的新人来说,引用的东西是如此令人困惑......
  • @felps321 不引用它会导致分词和文件名扩展,这不是您想要的。两者都是手册中的主题。你可以查一下。
  • 我的意思是,$@ 不是已经分词了吗? (对不起,很细致)
  • 是的,它会根据其实际内容“拆分”,但它们会保持原样,这与实际的分词不同,在实际分词中,"abc xyz" 之类的元素变为 "abc""xyz"。试试set -- "abc xyz" "123"; a=("$@"); b=($@); declare -p a; declare -p b。输出会告诉你差异。
  • 感谢您抽出宝贵时间回答我。祝你一切顺利
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多