如何在删除元素时迭代 bash 数组?

如何在删除元素时迭代 bash 数组?

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$parameterdarg="${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

相关内容