【问题标题】:Why doesn't this bor and bnot expression give the expected result in Powershell?为什么这个 bor 和 bnot 表达式在 Powershell 中没有给出预期的结果?
【发布时间】:2018-10-06 17:47:24
【问题描述】:

为什么这bor bnot在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

这是为什么?

【问题讨论】:

  • 你为什么期待ffff-bnot 0xffffffff0,为什么 0x0000 -bor 0 不应该是 0?顺便说一句,ffff:ffff:ffff::ffff:ffff:ffff:0000:0000:0000:0000:0000 的缩写。
  • 因为教程的缘故……可能是教程不好。
  • 我正在尝试一次做一个八位字节。

标签: powershell binary-operators


【解决方案1】:

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

您显示的完全扩展的计算正在执行此操作:

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 的模式,切换子网掩码,并在前缀结束的 bit 之间切换以及主机部分开始的

然后第 3 步 or 仅采用左侧的设置位以保持这些数字相同(既不是零也不是 ffff'd),所有是右侧的设置位( ffff 这些,将它们最大化到该前缀内的最大 IP 地址)。

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

教程说的地方:

& (AND), | (OR), ~ (NOT or 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

【讨论】:

  • 因此,如果 ipv6 地址中有 128 位...您必须在 PowerShell 中将其和子网掩码存储为 [decimal],因为 [decimal] 数据类型是 128-位...这是一个很大的变量!如果像这样存储地址:[decimal]$ipv6addr=0x20010db812340,我会在右边之后得到全零吗?因为如果我输入 [decimal]$ipv6addr=0x20010db8123400000000000000000000 我所做的只是被 pwsh 用 ParentContainsErrorRecordException 大喊大叫
  • 我已经编辑了要回复的答案,因为我想说的比评论还多。 (现在我明白你为什么要一次做一个八位字节了?哈哈)。
  • 呵呵...等等,这是为什么呢?为什么我要一次只做一个八位字节?我的意思是我在学校学习了按位运算符...前几天我在 Powershell 中使用位标志来显示一个 COM 对话框,其中我选择了 OK/OK 和 Cancel,以及 No Icon/Alert Icon/Stop Icon/Info Icon但这和这个不太一样……我敢肯定没有那么多位;我相信只有 32 个。
  • 我假设您将其拆分,因为您无法将 IPv6 地址或掩码放入 [int](即 [System.int32])中,直到您提到它。 (IPv4 适合 unsigned [uint32],但对于 IPv6 来说没有那么大了)
  • 请注意,在 ipv6 子网中查找最大 IP 地址直接取决于您在上面示例中的第 4 行中提供了多少 f's(15 个)。
猜你喜欢
  • 2013-11-21
  • 1970-01-01
  • 1970-01-01
  • 2015-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-20
  • 1970-01-01
相关资源
最近更新 更多