mask2cdr()
从像这样的点十进制网络掩码获取CIDR前缀:
255.255.192.0
您首先必须将四个八位字节转换为二进制数,然后计算最高有效位(即最高有效位数):
11111111.11111111.11000000.00000000 # 18 ones = /18 in CIDR
这个功能相当有创意。 首先,我们去除所有的前255个八位字节(即二进制全为1的八位字节),并将结果存储在变量x :
local x=${1##*255.}
这一步使用参数扩展 ,整个脚本非常依赖。 如果我们继续我们的例子255.255.192.0网络掩码,我们现在有以下值:
$1: 255.255.192.0 $x: 192.0
接下来我们设置三个变量: $1 , $2和$3 。 这些被称为位置参数 ; 它们很像普通的命名变量,但通常在将参数传递给脚本或函数时进行设置。 我们可以直接使用set --来设置值,例如:
set -- foo bar # $1 = foo, $2 = bar
我更喜欢在位置参数上使用命名变量,因为它使脚本更容易读取和调试,但最终结果是相同的。 我们将$1设置为:
0^^^128^192^224^240^248^252^254^
这实际上只是一个将某些十进制值转换为二进制值并计算1位数的表格。 我们稍后再回来。
我们设置$2
$(( (${#1} - ${#x})*2 ))
这看起来很复杂,但它实际上只是计算我们在第一个命令中删除的1位的数量。 它分解为:
(number of chars in $1 - number of chars in $x) * 2
这在我们的案例中是可行的
(13 - 5) * 2 = 16
我们剥去了两个八位字节,所以我们得到了十六个。
我们将$3设置为:
${x%%.*}
这是$x与第一个之后的所有东西的价值. 剥去。 在我们的情况下,这是192 。
我们需要将这个数字转换为二进制数,并计算其中的1位数,所以让我们回到我们的“转换表”。 我们可以将表格分成相等的四个字符块:
0^^^ 128^ 192^ 224^ 240^ 248^ 252^ 254^
在二进制中,上面的数字是:
00000000 10000000 11000000 11100000 11110000 11111000 11111100 11111110 # 0 ones 1 one 2 ones 3 ones ...
如果从左数起,表中的每个四字符块对应于二进制的附加1位。 我们试图转换192 ,所以我们首先从192开始,把表的最右边部分放掉,然后把它存储在x :
x=${1%%$3*}
$x的价值是现在
0^^^128^
其中包含两个四字符块,或二进制的两个1位。
现在,我们只需要从前255个八位字节(总计16个,存储在变量$2 )和上一个步骤(共$2 )中的1位中加起来:
echo $(( $2 + (${#x}/4) ))
哪里
${#x}/4
是$x的字符数除以4,即$x的四个字符块的数量。
输出:
18
cdr2mask()
让我们继续运行我们以前的例子,它有一个18的CIDR前缀。
我们使用set --来设置位置参数$ 1到$ 9:
$1: $(( 5 - ($1 / 8) )) # 5 - (18 / 8) = 3 [integer math] $2: 255 $3: 255 $4: 255 $5: 255 $6: $(( (255 << (8 - ($1 % 8))) & 255 )) # (255 << (8 - (18 % 8))) & 255 = 192 $7: 0 $8: 0 $9: 0
让我们来看看用来设置$1和$6的公式。 $1被设置为:
$(( 5 - ($1 / 8) ))
对于网络掩码,CIDR前缀的最大和最小可能值是32
11111111.11111111.11111111.11111111
和0的网络掩码
00000000.00000000.00000000.00000000
上面的公式使用整数除法,因此可能的结果范围从1到5:
5 - (32 / 8) = 1 5 - ( 0 / 8) = 5
$6被设置为:
$(( (255 << (8 - ($1 % 8))) & 255 ))
我们来分析一下18 CIDR前缀。 首先我们取模量,做一些减法:
8 - (18 % 8) = 6
接下来我们按位移255这个值:
255 << 6
这与在二进制中将六个0位推到255的末尾相同:
11111111000000
最后,我们按位与这个值255:
11111111000000 & 00000011111111 # 255
这使
00000011000000
或干脆
11000000
看起来熟悉? 这是我们在二进制网络掩码中的第三个八位字节:
11111111.11111111.11000000.00000000 ^------^
在十进制中,值是192。
接下来我们根据$1的值来移动位置参数:
[ $1 -gt 1 ] && shift $1 || shift
在我们的例子中, $1的值是3,所以我们将位置参数3移到左边。 前一个$4的值变成$1的新值, $1的前一个值变成$2的值,以此类推:
$1: 255 $2: 255 $3: 192 $4: 0 $5: 0 $6: 0
这些值应该看起来很熟悉:它们是来自我们的网络掩码的十进制八位字节(在最后附加了几个额外的零)。 为了获得网络掩码,我们只需打印出前四个点之间的点:
echo ${1-0}.${2-0}.${3-0}.${4-0}
如果参数未设置,则每个参数之后的-0表示使用0作为默认值。
输出:
255.255.192.0