【问题标题】:How to use a variable in a variable?如何在变量中使用变量?
【发布时间】:2013-02-13 07:21:26
【问题描述】:

我正在 ubuntu 专用服务器上编辑/扩展我的防火墙 bash 脚本。

下面的代码只是一个摘录。 下面的目的是为某些 IP 重新路由/打开我的(http、ftp、telnet 和 ssh)端口,用于/到 3 个盒子。

问题是我想在变量中使用变量。 所以--dport ${i}_${j}_port_ext 被 f.i. 正确替换。 --dport box0_http_port_ext 但不被视为变量(当然)。其实我想要的应该是--dport $box0_http_port_ext(注意开头的$

我尝试了几件事 f.i. --dport ${${i}_${j}_port_ext}--dport $(${i}_${j}_port_ext) 但这不好。

box0_http_port_ext="8080"
box0_ftp_port_ext="21"
box0_telnet_port_ext="23"
box0_ssh_port_ext="22"
#
allow_box0_http_port_ip="1.2.3.4 99.98.97.96 55.56.57.58"
allow_box0_ftp_port_ip="1.2.3.4 55.56.57.58"
allow_box0_telnet_port_ip="55.56.57.58"
allow_box0_ssh_port_ip="1.2.3.4"
#
for i in box0 box1 box2
do
  for j in http ftp telnet ssh
  do   
    for ips in $allow_${i}_${j}_port_ip
    do
      $IPTABLES -t nat -A PREROUTING -p tcp -i $LAN_IFACE -s $ips --dport ${i}_${j}_port_ext -j DNAT --to-destination ${i}_ip:${i}_${j}_port_int
    done
  done
done

请不要看代码,因为它是摘录,因此不完整。
问题是:如何使用$ibox0$jhttp 编码--dport $box0_http_port_ext。请记住,$i 也可以是 box1/box2$j 也可以替换为 ftp/telnet/ssh

【问题讨论】:

  • @ni_hao 请在解决问题后分享解决方案。

标签: bash shell variables ubuntu


【解决方案1】:

您可以使用间接变量引用(参见http://tldp.org/LDP/abs/html/bashver2.html#EX78

这在 Bash 版本 2 及更高版本中可用,在变量名之前使用 !,在 ${ } 内。

name=${i}_${j}_port_ext
echo ${!name}

工作示例:

#!/bin/bash
i=box0
j=http

box0_http_port_ext="hello1"
box2_telnet_port_ext="hello2"

name=${i}_${j}_port_ext
echo "varname: $name   value: ${!name}"

i="box2"
j="telnet"
name="${i}_${j}_port_ext"
echo "varname: $name   value: ${!name}"

输出

varname: box0_http_port_ext   value: hello1
varname: box2_telnet_port_ext   value: hello2

在上面的示例中,$name 返回字符串box0_http_port_ext,它是初始变量的名称。这相当于 ${name}。 ! 运算符将其右侧的字符串计算为变量名,并返回存储在变量中的值。所以${!name} 返回${box0_http_port_ext} 的值,即hello1

很遗憾 bash 不支持多维数组,不过可以用这个技巧来代替。

与其他答案的不同之处在于,$i_$j_port_ext 改为 ${i}_${j}_port_ext,以便 bash 知道变量名称在哪里结束。

【讨论】:

    【解决方案2】:

    试试这个:

    varname=${i}_${j}_port_ext
    ... --dport ${!varname} ...
    

    注意!里面${}

    已编辑:@user000001 关于分隔 i/j 变量名称的要点。

    【讨论】:

      【解决方案3】:

      请尝试转义脚本中的_ 字符

      --dport $i\_$j\_port\_ext
      

      【讨论】:

        【解决方案4】:

        谢谢你帮了我很多。

        顺便说一句,我确实注意到了 f.i. 之间的区别。 $name 和 {!name}。 $name 给出了变量的名称,其中 ${!name} 给出了变量的内容。这是唯一的解释吗?

        关于我的问题 i.r.t. 的(好)cmets。上面提到的摘录,这对我有用:

        for i in box0 box1 box2
        do
          for j in http ftp telnet ssh
          do
            ALLOWED_IPS=allow_${i}_${j}_port_ip
            for ips in ${!ALLOWED_IPS}; do
            do
              PORT_EXT=${i}_${j}_port_ext; PORT_INT=${i}_${j}_port_int; IP=${i}_ip
              $IPTABLES -t nat -A PREROUTING -p tcp -i $LAN_IFACE -s $ips --dport ${!PORT_EXT} -j DNAT --to-destination ${!IP}:${!PORT_INT}
            done
          done
        done
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-01-17
          • 1970-01-01
          • 2011-10-04
          • 1970-01-01
          • 2016-05-08
          • 2010-12-05
          相关资源
          最近更新 更多