如何在变量中使用变量?

时间:2013-02-13 07:21:27

标签: bash shell variables ubuntu

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

下面的代码只是摘录。 以下目的是为我的(http,ftp,telnet和ssh)端口重新路由/打开一些IP / 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

请不要查看代码,因为它是摘录,因此不完整 问题是:如何通过对{em> box0 使用--dport $box0_http_port_ext和为 http 使用$i来对$j进行编码。请记住,$i也可以是 box1 / box2 ,而$j也可以替换为 ftp / telnet / ssh

4 个答案:

答案 0 :(得分:5)

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

这可以在 Bash Version 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返回sting box0_http_port_ext,它是初始变量的名称。这相当于$ {name}。 !运算符将字符串作为变量名称计算在其右侧,并返回存储在变量中的值。因此${!name}会返回${box0_http_port_ext}的值hello1

不幸的是,bash不支持多维数组,但可以使用此技巧。

与其他答案的区别在于$i_$j_port_ext更改为${i}_${j}_port_ext,以便bash知道变量名称的结束位置。

答案 1 :(得分:2)

试试这个:

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

注意!在${}

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

答案 2 :(得分:0)

请尝试在脚本

中转义_个字符
--dport $i\_$j\_port\_ext

答案 3 :(得分:0)

谢谢你帮了我很多。

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

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

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