요소를 제거하는 동안 bash 배열을 반복하는 방법은 무엇입니까?

요소를 제거하는 동안 bash 배열을 반복하는 방법은 무엇입니까?

GNU 배쉬, 버전 4.3.42(1)-릴리스(arm-openwrt-linux-gnu)

Bash 배열을 사용하여 iptables 규칙을 스크립팅하려고 합니다.

$NETID는 네트워크 주소를 만드는 데 사용됩니다. 예를 들어 192.168.10.0/24, 192.168.20.0/24 등

${NETID[@]}의 "i"가 다음과 같은 임시 변수($NETID_TMP)를 만들려고 합니다.삭제됨$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

관련 정보