从命令行调用 Bash 脚本变量

Calling a Bash script variable from the commandline

我有一个接受命令行参数的 Bash 脚本。该脚本定义了几个字符串数组。该参数确定我要打印哪个数组。由于有许多不同的可能数组集可供选择,我希望能够在命令行上准确指定要打印的数组。

例如,假设我定义了这些数组:

#/bin/bash
myarray1=(abc 123)
myarray2=(def 456)
myarray3=(ghi 789)
myarray4=(jkl 012)
myarray5=(mno 345)
myarray6=(pqr 678)
myarray7=(stu 901)

我想从命令行中选择是否要打印所有数组,或者这些数组的各种组合,例如 myarray1myarray3myarray4。但是在另一个 运行 上,我只想打印 myarray5myarray7.

理想情况下,我希望能够 运行 像这样的脚本:

np ~/usr-bin > bash myscript.bash myarray1 myarray3 myarray4

所以输出是这样的:

abc 123
ghi 789
jkl 012

或者像这样:

np ~/usr-bin > bash myscript.bash myarray5 myarray7

所以输出是这样的:

mno 345
stu 901

我想 Bash 接受这些参数并识别它们是 array/variable 名称,然后像我这样做一样打印它们:echo

我之前几乎没有编写过任何 Bash 脚本,而且我尝试使用的方法似乎不起作用。这是可能的,还是有比我尝试的方法更好的方法来实现这一点?

您可以使用 !:

为变量扩展引入一个间接级别
#/bin/bash

myarray1=(abc 123)
myarray2=(def 456)
myarray3=(ghi 789)
myarray4=(jkl 012)
myarray5=(mno 345)
myarray6=(pqr 678)
myarray7=(stu 901)

for i in $*; do
    echo ${!i}
done

运行 使用 testscript myarray6 myarray2 将输出:

pqr
def

如果你想确保它不会为不存在的变量提供空行,你可以使用:

#/bin/bash

myarray1=(abc 123)
myarray2=(def 456)
myarray3=(ghi 789)
myarray4=(jkl 012)
myarray5=(mno 345)
myarray6=(pqr 678)
myarray7=(stu 901)

for i in $*; do
    if [[ ! -z "${!i}" ]]; then
        echo ${!i}
    fi
done

运行 testscript myarray6 xyzzy_plugh myarray2 仍然 输出:

pqr
def

(假设您没有名为 xyzzy_plugh 的环境变量,但是,除非您是 Colossal Caves 的粉丝,否则为什么要这么做?)。

从 Bash 4.3 (2014-02-26) 开始,您可以使用 namerefs 作为简单的解决方案:

print_arrays() {
  for a in "$@"; do
    # This makes _t_ an alias for the variable whose name is $a
    declare -n _t_="$a"
    echo "${_t_[@]}"
  done
}

4.3之前,需要使用!间接语法。但是,间接通过的变量需要包含整个数组引用,包括下标。而且您只能通过变量间接访问,而不是字符串表达式。所以你需要做这样的事情:

print_arrays() {
  for a in "$@"; do
    # Construct the "name", which is the subscripted array name
    _t_=${a}[@]
    echo "${!_t_}"
  done
}

如果您是 Bash 的新手,您应该阅读 Bash manual section on arrays,其中解释了奇怪的语法 "${array[@]}"。此处 _t_ 的定义旨在创建该语法;它本身不是下标表达式。