GNU bash,版本 4.3.42(1)-release (arm-openwrt-linux-gnu)
我正在尝试使用 bash 数组编写 iptables 规则脚本。
$NETID 用于创建网络地址。例如,192.168。10.0/24, 192.168。20.0/24等
我正在尝试创建一个临时变量($NETID_TMP),其中 ${NETID[@]} 中的“i”是已删除来自 $NETID_TMP。例如,如果“i”= 10,则 NETID_TMP=(20 30 40)。
脚本:
#!/opt/bin/bash
NETID=(10 20 30 40)
for (( i=0; i<${#NETID[@]}; i++ )); do
NETID_TMP=(${NETID[*]})
unset NETID_TMP[${NETID[i]}]
iptables -I FORWARD -s 192.168.${NETID[i]}.0/24 -d 192.168.${NETID_TMP[0]}.0/24,192.168.${NETID_TMP[1]}.0/24,192.168.${NETID_TMP[2]}.0/24 -j DROP
done
结果应该是...
iptables -I FORWARD -s 192.168.10.0/24 -d 192.168.20.0/24,192.168.30.0/24,192.168.40.0/24 -j DROP
iptables -I FORWARD -s 192.168.20.0/24 -d 192.168.10.0/24,192.168.30.0/24,192.168.40.0/24 -j DROP
iptables -I FORWARD -s 192.168.30.0/24 -d 192.168.10.0/24,192.168.20.0/24,192.168.40.0/24 -j DROP
iptables -I FORWARD -s 192.168.40.0/24 -d 192.168.10.0/24,192.168.20.0/24,192.168.30.0/24 -j DROP
答案1
netid=(10 20 30 40)
for i in "${netid[@]}"; do
out="iptables -I FORWARD -s 192.168.$i.0/24 -d "
for j in "${netid[@]}"; do
(( i == j )) && continue
out+="192.168.$j.0/24,"
done
out="${out%,} -j DROP"
printf '%s\n' "$out"
done
这个 Bash 脚本产生
iptables -I FORWARD -s 192.168.10.0/24 -d 192.168.20.0/24,192.168.30.0/24,192.168.40.0/24 -j DROP
iptables -I FORWARD -s 192.168.20.0/24 -d 192.168.10.0/24,192.168.30.0/24,192.168.40.0/24 -j DROP
iptables -I FORWARD -s 192.168.30.0/24 -d 192.168.10.0/24,192.168.20.0/24,192.168.40.0/24 -j DROP
iptables -I FORWARD -s 192.168.40.0/24 -d 192.168.10.0/24,192.168.20.0/24,192.168.30.0/24 -j DROP
通过双循环。内部循环会跳过循环变量在数值上等于外部循环的循环变量的迭代,以创建所需的效果。
一旦你有了字符串$out
,你就可以eval
了。
或者,要避免eval
:
netid=(10 20 30 40)
for i in "${netid[@]}"; do
sarg="192.168.$i.0/24"
darg=""
for j in "${netid[@]}"; do
(( i == j )) && continue
darg+="192.168.$j.0/24,"
done
darg="${darg%,}"
iptables -I FORWARD -s "$sarg" -d "$darg" -j DROP
done
变量替换将从 的最末尾${parameter%word}
删除,因此将删除 af 末尾的逗号。word
$parameter
darg="${darg%,}"
$darg
评论中的问题后更新:
bash
上面唯一特定的事情是使用数组$netid
、+=
附加到$darg
字符串的运算符和((...))
。我们可以把它变成sh
这样的脚本(这里假设$IFS
仍然有它的默认值):
netid="10 20 30 40"
for i in $netid; do
sarg="192.168.$i.0/24"
darg=""
for j in $netid; do
[ "$i" -eq "$j" ] && continue
darg="${darg}192.168.$j.0/24,"
done
darg="${darg%,}"
iptables -I FORWARD -s "$sarg" -d "$darg" -j DROP
done
如果您想要插入一个单独的数字列表$darg
,请在内部循环中使用它来代替$netid
。它应该是一串以空格分隔的数字。
答案2
使用以下方法更容易zsh
:
#! /bin/zsh -
nets=(192.168.{10,20,30,40}.0/24)
for net ($nets) iptables -I FORWARD -s $net -d ${(j:,:)nets:#$net} -j DROP