嵌套Bash while循环,内循环只是循环循环

时间:2016-02-04 04:00:44

标签: bash shell loops while-loop nested-loops

这是一个非常简单的脚本,但我似乎无法做到正确。此代码应打印出来自192.168.0.0 - 192.168.255.255的C类IP地址,但打印出的所有内容均为192.168.0.0 - 192.168.0.255。由于某种原因,我的外部循环不会循环。我确定这是一个愚蠢的东西,但这对于那些学习shell脚本中的嵌套循环的人来说可能会有所帮助。欢迎任何其他建议!

#! /bin/sh
network_id="192.168."
count1=-1
count2=-1
while [ "$count1" -le 254 ]
do
    count1=$(($count1+1))
    while [ "$count2" -le 254 ]
    do
        count2=$(($count2+1))
        printf "%s%s%s%s\n" $network_id $count1 "." $count2
    done
done
exit 0

6 个答案:

答案 0 :(得分:2)

您没有重置count2。你的外循环运行了256次,但内循环在运行一次后停止。

如果在关闭内部循环后添加count2=-1,它将按预期工作。

为了清楚起见,我会移动你的增量,所以你显然在0-255之间迭代。以下是我的写作方式:

#! /bin/sh
network_id="192.168."
count1=0
count2=0
while [ "$count1" -le 255 ]; do
    while [ "$count2" -le 255 ]; do
        printf "%s%s%s%s\n" $network_id $count1 "." $count2
        count2=$(($count2+1))
    done
    count2=0
    count1=$(($count1+1))
done

答案 1 :(得分:2)

只是一个小错误。你没有设置$count=-1

#! /bin/sh
network_id="192.168."
count1=-1
count2=-1
while [ "$count1" -le 254 ]
do
    count1=$(($count1+1))
    while [ "$count2" -le 254 ]
    do
        count2=$(($count2+1))
        printf "%s%s%s%s\n" $network_id $count1 "." $count2
    done
    count2=-1
done
exit 0

这应该有用。

答案 2 :(得分:2)

好吧,@uint128_t发现错误。

您的脚本似乎试图打印出192.168.0.0/16内的所有IP地址,而不是所有带有该前缀的C类网络,因此我假设您的代码更好您正在寻找的结果的描述。

我将提交以下内容作为"更好地使用bash":

#!/usr/bin/env bash

# Declare an array
ip=(192 168 -1 -1)

# Step through the third quad in the array
while [ $((ip[2]++)) -lt 255 ]; do
    # Step through the fourth quad in the array
    while [ $((ip[3]++)) -lt 255 ]; do
        # Print the array, with dots as a field separator
        IFS=. eval echo '"${ip[*]}"'
    done
    # Reset the last quad once we're done with this subnet
    ip[3]=-1
done

会有人说eval是邪恶的,但在这种情况下它是完全安全的,输入数据是已知的,你用单引号保护事物。

此解决方案可以避免额外的计数器,如果您愿意,也可以灵活地使用您的IP进行其他操作。

我应该提到另一个微妙之处,即[ $((ip[2]++)) -lt 255 ]。这会增加数组元素,但由于++在变量之后,用于比较的值(-le)是增量发生之前的值。因此,当比较数小于255时,我们停止循环,因为这意味着当变量增加一个更高时,循环的最后一次运行将发生到255.如果由于某种原因你想比较增量后的值而不是之前,您可以使用++添加变量,而不是追加它:$((++ip[2]))

另一个有趣的方法可能是利用IP地址只是数字这一事实,而虚线四边形是该数字的翻译:

#!/usr/bin/env bash

# Set your start and maximum IPs as integers
ip=$(( 192*2**24 + 168*2**16 ))
max=$(( ip + 255*2**8 + 255 ))

# Convert each integer into dotted quad notation
while [ $ip -le $max ]; do
  echo $(( ip/2**24 )).$(( ip/2**16 %256 )).$(( ip/2**8 % 256 )).$(( ip % 256 ))
  ((ip++))
done

答案 3 :(得分:1)

For循环比while循环更好。您的实施可以简化为:

.thumb {
    display: inline-block;
    float: none;
    margin: 0 5px 5px;
    width: 150px;
}
  

编辑:感谢ghoti的建议。请注意,您可能需要自定义shebang系列以满足您的需求。可在以下位置找到更多讨论:What is difference between #!/bin/sh and #!/bin/bash?Why is it better to use “#!/usr/bin/env NAME” instead of ...

答案 4 :(得分:1)

您应该在外部循环的开头初始化count2,而不是在外部循环之前。否则,内循环中的测试在第一次通过外循环后会立即失败。

#! /bin/sh
network_id="192.168."
count1=-1
while [ "$count1" -le 254 ]
do
    count1=$(($count1+1))
    count2=-1
    while [ "$count2" -le 254 ]
    do
        count2=$(($count2+1))
        printf "%s%s%s%s\n" $network_id $count1 "." $count2
    done
done
exit 0

答案 5 :(得分:1)

你可以使用1循环:

i=0
((max=256 * 256))
while [ $i -lt ${max} ]; do
        (( major=i/256))
        (( minor=i%256))
        printf "%s.%s.%s.%s\n" "192" "168"  ${major} ${minor}
        ((++i))
done