bash – 在两个IPv4地址之间以CIDR表示法查找IPv4网络的算法
我想找出这两个网络之间CIDR表示法中的所有IPv4网络:
10.11.3.64-10.11.3.127 10.11.52.0-10.11.52.255 IPv4网络应具有尽可能短的子网掩码. 将10.11.3.127转换为二进制,添加1并转换回十进制以获得网络的第一个地址相当容易.然后将10.11.52.0转换为二进制,减去1并转换回十进制,以获得网络的最后一个地址.但是,为了找出10.11.3.128-10.11.51.255范围内的CIDR块,有哪些建议哪些算法很聪明?只是一个建议,我认为哪个方向应该足够:) 解决方法
我真的很喜欢这个问题,我昨晚看了一眼并决定试一试.在这一点上,我有一个概念证明shell脚本工作.
免责声明: >这只是一个概念证明 值得一提的另一件事是我的理解: IPv4网络应具有尽可能短的子网掩码. 我们应该尝试从保留的8位网络到提供的最大cidr,在这种情况下为25. 好的,让我们看看脚本在运行: [root@TIAGO-TEST2 tmp]# time bash ip.sh 10.11.3.64/25 10.11.52.0/24 10.11.3.128/25 10.11.4.0/22 10.11.8.0/21 10.11.16.0/20 10.11.32.0/20 10.11.48.0/22 real 0m48.376s user 0m6.174s sys 0m34.644s 代码下方: #! /bin/bash function split_octet { sed -re "s/./ /g" <<< "$1" } function dec2bin { perl -e 'printf "%0'"$1"'bn",'"$2"';' } function bin2dec { perl -le 'print 0b'"$1"';' } function ip2bin { str="" for octet in $(split_octet $1); do str="${str}$(dec2bin 8 $octet)" done echo "$str" } function bin2ip { str="" for octet in $(grep -Eo '.{8}' <<< $1); do dec=$(bin2dec $octet) str="${str}.${dec}" done echo "$str" | sed -re 's/^.|.$//g' } function ip2dec { ip=$1 bin2dec $(ip2bin $ip ) } function dec2ip { dec=$1 bin2ip $(dec2bin 32 $dec ) } function AND { perl -e ' $a=0b'"$1"' & 0b'"$2"'; printf "%032bn",$a ' } function OR { perl -e ' $a=0b'"$1"' | 0b'"$2"'; printf "%032bn",$a ' } function NOT { perl -le ' $a= (~ 0b'"$1"') & 0xFFFFFFFF; printf "%032bn",$a ' } function get_network { ip=$1; mask=$2; if [ -n "$ip" -a -n "$mask" ];then echo $(bin2ip $(AND $(ip2bin $ip) $(ip2bin $mask))) return fi grep -qP "d+.d+.d+.d+/d+" <<< "$ip" if [ "$?" == 0 ];then ip=$(get_ip_from_cidr $1 ) mask=$(get_mask_from_cidr $1) echo $( bin2ip $(AND $(ip2bin $ip) $(ip2bin $mask))) fi } function get_broadcast { ip=$1; mask=$2; if [ -n "$ip" -a -n "$mask" ];then echo $( bin2ip $(OR $(ip2bin $ip) $(NOT $(ip2bin $mask) ) )) return fi grep -qP "d+.d+.d+.d+/d+" <<< "$ip" if [ "$?" == 0 ];then ip=$(get_ip_from_cidr $1 ) mask=$(get_mask_from_cidr $1) echo $( bin2ip $(OR $(ip2bin $ip) $(NOT $(ip2bin $mask) ) )) fi } function get_ip_from_cidr { awk -F/ '{print $1}' <<< "$1" } function get_mask_from_cidr { mask=$(awk -F/ '{print $2}' <<< "$1") mask=$(cidr $mask) mask=$(bin2ip $mask) echo $mask } function cidr { perl -e ' $n='"$1"'; $diff=32-$n; print "1"x$n . "0"x$diff; ' } snet_cidr=$1 enet_cidr=$2 largest_cidr=$(echo -e "$snet_cidrn$enet_cidr"| awk -F/ '{print $2}' | sort -rn | head -1 ) snet_dec=$( ip2dec $(get_ip_from_cidr $snet_cidr)) enet_dec=$( ip2dec $(get_ip_from_cidr $enet_cidr)) sbc_ip=$(get_broadcast $snet_cidr) ebc_ip=$(get_broadcast $enet_cidr) sbc_dec=$(ip2dec $sbc_ip) ebc_dec=$(ip2dec $ebc_ip) counter=$sbc_dec while [ $counter -lt $enet_dec ];do tip=$(dec2ip $counter) for cidr in $(seq 8 $largest_cidr) ; do tnet_ip=$(get_network $tip/$cidr) tnet_cidr=$tnet_ip/$cidr tbc_ip=$(get_broadcast $tnet_cidr) tnet_dec=$( ip2dec $(get_ip_from_cidr $tnet_cidr)) tbc_dec=$(ip2dec $tbc_ip) if [ $sbc_dec -lt $tnet_dec -a $enet_dec -gt $tbc_dec ];then echo $tnet_cidr counter=$tbc_dec break fi done let counter++ done 编辑解释这些变量是什么可能是一个好主意: > snet_cidr:以cidr表示法启动net 无论你在哪里看到tnet或tbc都是temp net,temp broadcast,temp,因为它在循环内部. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |