IPv4地址是32位无符号整数。"点分十进制"表示法(192.168.1.2)只是表示此类地址的一种方式。在应用子网掩码时,如果我们先将点分十进制格式转换为纯整数,会更容易操作。
有几种方法可以实现这一点,但以下是其中最简单的一种方法:
ip2int() { local o # array of octets (bytes) IFS=. read -ra o <<<"$1" echo "$(((o[0] << 24) + (o[1] << 16) + (o[2] << 8) + o[3]))"}int2ip() { echo "\$((($1 >> 24) & 0xFF)).\$((($1 >> 16) & 0xFF)).\$((($1 >> 8) & 0xFF)).\$(($1 & 0xFF))"}使用这些函数,我们可以进行双向转换:
$ ip2int 192.168.10.13232238081$ int2ip 3232238081192.168.10.1要应用子网掩码,我们先将子网掩码转换为整数,然后进行按位与运算以获取网络部分:
$ ip2int 255.255.255.04294967040$ echo $((3232238081 & 4294967040))3232238080$ int2ip 3232238080192.168.10.0主机部分的处理方式类似:首先对子网掩码取反,然后进行相同的按位与运算。在取反后,我们只需保留最低的32位;否则,Bash的64位整数可能会给我们一些奇怪的结果。
$ echo $((~4294967040 & 0xffffffff))255$ echo $((3232238081 & 255))1$ int2ip 10.0.0.1同样的原理适用于任何大小的子网掩码。例如,a/23 子网掩码看起来如下:
$ int2ip $((0xfffffe00))255.255.254.0$ int2ip $((2#11111111111111111111111000000000))255.255.254.0十六进制常量0xfffffe00与二进制常量2#11111111111111111111111000000000相同,但写起来更方便,并且更容易由人类验证。
如果你想学习如何编写更加健壮和可靠的 Shell 脚本,减少生产环境中的错误和故障,那么关注我吧!我会分享 Shell 编程的最佳实践和建议,帮助你提高 Shell 脚本的鲁棒性和可维护性。如果你想深入了解 Shell 编程的实际应用和技巧,可以关注我的《Shell 脚本编程最佳实践》专栏,里面有我在一线互联网大厂的实际生产经验和最佳实践,帮助你高效完成各种自动化任务。