【问题标题】:Calling a Bash script variable from the commandline从命令行调用 Bash 脚本变量
【发布时间】:2015-04-24 08:50:24
【问题描述】:

我有一个接受命令行参数的 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 接受这些参数并识别它们是数组/变量名称,然后像我这样做一样打印它们:echo $1

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

【问题讨论】:

    标签: arrays bash command-line arguments


    【解决方案1】:

    从 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_ 的定义旨在创建该语法;它本身不是下标表达式。

    【讨论】:

    • 我在运行您的第一个示例时遇到错误,但我完全忘记了这台机器上的 bash 版本是 4.1,而不是 4.3。你的第二个例子成功了。谢谢!
    • Bash 版本 - 3.0:2004-07-27、4.0:2009-02-20、4.1:2010-05、4.2: 2011-02Shellshock patch 4.3.027 on 2014-10-01。 4.3 的(发布)日期是什么时候?
    【解决方案2】:

    您可以使用! 为变量扩展引入一个间接级别:

    #/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 的粉丝,否则为什么会这样做?)。

    【讨论】:

    • 有没有办法让这个解决方案打印数组中的两个(所有)项目?如果可能的话,这是解决我问题的理想方法。
    猜你喜欢
    • 2012-10-30
    • 2011-06-04
    • 1970-01-01
    • 2011-10-16
    • 2021-01-28
    • 1970-01-01
    • 1970-01-01
    • 2011-05-06
    • 2010-10-22
    相关资源
    最近更新 更多