【问题标题】:Assign value to a variable in unix dynamically - variable indirection动态为unix中的变量赋值 - 变量间接
【发布时间】:2014-06-03 23:35:17
【问题描述】:
HOST_NAME_="localhost:8080" 
HOST_NAME_stg="stg.com:8080"
HOST_NAME_qa="qa.com:8080"
HOST_NAME=${!"HOST_NAME_$1"}

echo -n ${HOST_NAME}

我收到错误替换错误。但是如果传递的参数是 stg,我希望打印 stg.com:8080。我该怎么做

【问题讨论】:

    标签: shell unix indirection


    【解决方案1】:

    注意:鉴于您使用 ${!...} 间接引用变量,我假设您使用 bash - 仅 POSIX 功能的 shell和许多其他人不支持此功能(至少使用此语法)。

    尝试以下方法:

    HOST_NAME_="localhost:8080" 
    HOST_NAME_stg="stg.com:8080"
    HOST_NAME_qa="qa.com:8080"
    
    HOST_NAME_INDIRECT=HOST_NAME_$1
    
    HOST_NAME=${!HOST_NAME_INDIRECT}
    
    echo -n "${HOST_NAME}"
    

    当使用${!...} 间接引用变量时,包含目标变量名称的参数本身必须是变量,而不是字符串文字,因此是中间变量@ 987654325@.

    同时考虑避免使用全大写的变量名,以避免与标准环境变量(例如$HOSTNAME)和特殊的shell变量(例如$SECONDS)发生潜在冲突。


    下面是各种流行的shell如何做变量间接

    假设以下两个变量:

    a='value of a'
    nameOfA='a'
    
    • bash

       echo "${!nameOfA}" # -> 'value of a'
      
       # bash 4.3+
       declare -n aliasOfA='a'  # in functions: `local -n`
       echo "$aliasOfA"         # same as `echo "$a"` -> 'value of a'
      
    • zsh

      echo "${(P)nameOfA}"  # -> 'value of a'
      
    • ksh93+:

       nameref aliasOfA='a'  # same as `typeset -n`
       echo "$aliasOfA"      # same as `echo "$a"` -> 'value of a'
      
    • sh(仅 POSIX 功能的 shell)

       eval echo \"'$'$nameOfA\"  # -> 'value of a'
      

    警告:使用eval 可能不安全。如果$nameOfA 包含类似'a; $(rm *)' 的内容,则rm 命令也会执行。

    【讨论】:

    • 感谢您提供如此详细的答案。这确实解决了我的问题,但我想知道更多关于为什么 eval 不安全的详细信息。我查看了一些关于 eval 的 stackoverflow 链接,但他们只是添加到歧义。如果您知道一些谈论 eval 的好消息来源,您可以在此处发布。谢谢
    • @AbhijeetKushe:简而言之:传递给eval 的字符串可以包含any 命令。如果您无法完全控制该字符串 - 例如,如果它是从调用脚本传递的 - 它可能包含无意或恶意执行您不想要或不期望的事情的命令。假设有人将qa; $(rm ...) 而不是qa 作为$1 传递给您的脚本。这是一个人为的例子,但向您展示了不想要的事情如何发生的原理。这并不是说必须从不使用eval - 只是要意识到它的危险并将使用限制在谨慎控制的情况下。
    【解决方案2】:

    感谢您的回复。是的,使用临时变量确实可以解决问题。但是我想知道这样做是否可以达到目的,但它有点复杂

    eval "HOST_NAME=\$HOST_NAME_$2"
    

    【讨论】:

    • 虽然您的版本具有在所有类似 Bourne 的 shell 中工作的优势,但它可能不安全,因为它使用 eval。因此,在bash 中,我建议您使用${!...} 方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-13
    相关资源
    最近更新 更多