为什么这个bor和bnot表达式不能在Powershell中给出预期的结果?

时间:2018-04-26 06:17:41

标签: powershell binary-operators

为什么不能在PowerShell中给出预期的结果?

要查找ipv6子网中的最后一个地址,需要执行“二进制”或“二进制”操作。

我正在阅读的文章(https://www.codeproject.com/Articles/660429/Subnetting-with-IPv6-Part-1-2)描述如下:

(2001:db8:1234::) | ~(ffff:ffff:ffff::) = 2001:db8:1234:ffff:ffff:ffff:ffff:ffff

其中|是“二元或”和 〜是“二元不”

然而,在powershell中,我试着像:

$mask = 0xffffffff
$someOctet = 0x0000
"{0:x4}" -f ($someOctet -bor -bnot ($mask) )

我得0000而不是ffff

为什么会这样?

1 个答案:

答案 0 :(得分:2)

本教程正在执行整个子网掩码的-not,因此ff00反转为00ff,类似于更长的Fs和0;你没有那样做,所以你得不到同样的结果。

您展示的完全展开的计算是:

1. (2001:0db8:1234:0000:0000:0000:0000:0000) | ~(ffff:ffff:ffff:0000:0000:0000:0000:0000) 

2. (2001:0db8:1234:0000:0000:0000:0000:0000) |  (0000:0000:0000:ffff:ffff:ffff:ffff:ffff) 

3. = 2001:db8:1234:ffff:ffff:ffff:ffff:ffff

注意在步骤1到步骤2中,not是如何反转Fs和0s的模式,切换子网掩码,并在之间切换它前缀结束,主机部分开始的

然后步骤3 or只取左边的设置位来保持这些数字相同(既不是零也不是ffff),而 all 来自对(对于那些,将它们最大化到该前缀中的最大IP地址)。

换句话说,这样做“一次八位一组”是没有意义的。这是一个完整的IP地址(或整个前缀)+整个子网掩码操作。

教程说:

  

&安培; (AND),| (OR),〜(NOT或bit INVERTER):我们将在计算中使用这三个按位运算符。我认为每个人都很熟悉 - 至少从大学的数字逻辑课程中 - 并且知道它们是如何运作的。我不会再在这里解释细节。您可以搜索“按位运算符”以获取更多信息。

如果您对他们的工作不是很熟悉,那么在尝试将它们应用于IP子网之前,还是值得研究一下。因为你基本上问为什么0 or (not 1)0而答案是因为这就是布尔逻辑“或”和“不”的工作方式。

编辑您的评论

[math]::pow(2,128)[decimal]::maxvalue大很多,所以我不认为Decimal会这么做。

我不知道推荐的方法是什么,但我想如果您真的想在PowerShell中使用-not完成所有操作,则必须使用[bigint]处理它(例如[bigint]::Parse('20010db8123400000000000000000000', 'hex'))。

但更有可能的是,你会做更长篇大论的事情,如:

# parse the address and mask into IP address objects
# which saves you having to expand the short version to 
$ip = [ipaddress]::Parse('fe80::1')
$mask = [ipaddress]::Parse('ffff::')


# Convert them into byte arrays, then convert those into BitArrays
$ipBits = [System.Collections.BitArray]::new($ip.GetAddressBytes())
$maskBits = [System.Collections.BitArray]::new($mask.GetAddressBytes())


# ip OR (NOT mask) calculation using BitArray's own methods
$result = $ipBits.Or($maskBits.Not())


# long-winded way to get the resulting BitArray back to an IP
# via a byte array

$byteTemp = [byte[]]::new(16)
$result.CopyTo($byteTemp, 0)
$maxIP = [ipaddress]::new($byteTemp)

$maxIP.IPAddressToString

# fe80:ffff:ffff:ffff:ffff:ffff:ffff:ffff