Scripting 在Powershell中,什么';将两个表合并为一个表的最佳方式是什么?
我是Powershell的新手,我想知道是否有人知道实现以下示例问题的更好方法 我有一个从IP地址到主机名的映射数组。这表示活动DHCP租约的列表:Scripting 在Powershell中,什么';将两个表合并为一个表的最佳方式是什么?,scripting,powershell,dhcp,Scripting,Powershell,Dhcp,我是Powershell的新手,我想知道是否有人知道实现以下示例问题的更好方法 我有一个从IP地址到主机名的映射数组。这表示活动DHCP租约的列表: PS H:\> $leases IP Name -- ---- 192.168.1.1 Apple 192.168.1.2 Pear 192.168.1.3 Banana 192.168.1.99
PS H:\> $leases
IP Name
-- ----
192.168.1.1 Apple
192.168.1.2 Pear
192.168.1.3 Banana
192.168.1.99 FishyPC
我有另一个从MAC地址到IP地址的映射数组。这表示IP保留的列表:
PS H:\> $reservations
IP MAC
-- ---
192.168.1.1 001D606839C2
192.168.1.2 00E018782BE1
192.168.1.3 0022192AF09C
192.168.1.4 0013D4352A0D
为了方便起见,我能够使用下面的代码生成从MAC地址到IP地址和主机名的第三个映射数组。其思想是,$reservations
应该得到第三个字段“Name”,只要有匹配的“IP”字段,就会填充该字段:
所需的输出如下所示:
PS H:\> $ideal
IP MAC Name
-- --- ----
192.168.1.1 001D606839C2 Apple
192.168.1.2 00E018782BE1 Pear
192.168.1.3 0022192AF09C Banana
192.168.1.4 0013D4352A0D
有没有更好的方法呢?李·霍姆斯写了一篇你想要的文章。太糟糕了,它还没有内置到PowerShell中。1.5年后,我在原始答案中粘贴的cmdlet经过了多次更新,已经完全过时。因此,我已将和替换为指向最新版本的链接 主要功能:
- 直观(类SQL)语法
- 智能物业合并
- 用于更新、合并和特定联接类型的预定义联接命令
- 为(左)输入对象和输出对象定义良好的管道(正确使用时保留内存)
- 与大型对象列表上的比较对象相比,执行速度快约40%
- 支持(自定义)对象、数据表和字典(如哈希表)进行输入
- 智能特性和计算特性表达式
- 自定义关系表达式
- 易于安装(dot采购)
- 支持PowerShell for Windows(5.1)和PowerShell核心
Install-Script -Name Join
Join Object cmdlet显示以下代理命令及其自己的(-JoinType
和-Property
)默认值:
(别名InnerJoin对象
或InnerJoin
),组合相关对象Join
(别名LeftJoin对象
),组合相关对象并添加其余的左对象LeftJoin
(别名RightJoin对象
),组合相关对象并添加其余的右对象RightJoin
(别名FullJoin对象
),组合相关对象并添加其余的左、右对象FullJoin
(别名CrossJoin对象
),将每个左对象与每个右对象组合在一起CrossJoin
(别名更新对象
),用相关的右对象更新左对象更新
(别名Merge Object
),用相关的右对象更新左对象,并添加其余新的(不相关的)右对象Merge
Join-Object
cmdlet有两个版本(两个版本提供相同的功能):
Join.psm1
模块重命名为Join.ps1
脚本文件)并通过以下方式调用脚本: 答复 要回答问题中的实际示例:
$reservations | LeftJoin $leases -On IP
IP MAC Name
-- --- ----
192.168.1.1 001D606839C2 Apple
192.168.1.2 00E018782BE1 Pear
192.168.1.3 0022192AF09C Banana
192.168.1.4 0013D4352A0D
例子
更多示例可在相关Stackoverflow问题中找到,网址为:
请给出一个您可以像这样使用脚本块
$leases | select IP, NAME, @{N='MAC';E={$tmp=$_.IP;($reservations| ? IP -eq $tmp).MAC}}
下面是一个使用哈希表的简单示例。使用大型阵列时,速度会更快
$leases =
'IP,Name
192.168.1.1,Apple
192.168.1.2,Pear
192.168.1.3,Banana
192.168.1.99,FishyPC' | convertfrom-csv
$reservations =
'IP,MAC
192.168.1.1,001D606839C2
192.168.1.2,00E018782BE1
192.168.1.3,0022192AF09C
192.168.1.4,0013D4352A0D' | convertfrom-csv
$hashRes=@{}
foreach ($resRecord in $reservations) {
$hashRes[$resRecord.IP] = $resRecord
}
$leases | foreach {
$other = $hashRes[$_.IP]
[pscustomobject]@{IP=$_.IP
MAC=$other.MAC
Name=$_.name}
}
这也可以使用我的模块完成 关于性能,我针对100k行的样本数据进行了测试:
Join Object
by me运行14秒LeftJoin
在1分50秒内运行几乎令人难以置信的是,这仍然没有包括在PowerShell@Michael您是如何获得所有活动租约的IP地址到主机名的表的?我一直在使用DHCP模块,但无法理解它。我还尝试合并一些表。@Ruisu我在使用
netsh
的dhcp命令获取列表,然后用正则表达式解析输出。还有,但它仅对本机代码可用。我不知道有哪个powershell模块或.net库可以做这种事情。我最终将P/Invoke包装器写入DHCP服务器管理API。下面是另一个示例:修订更新:将-Expressions[HashTable]
和-DefaultExpression[ScriptBlock]
参数合并到单个-Merge[HashTable|ScriptBlock]
支持特定合并表达式的哈希表
,或公共合并表达式的脚本块
。解决了左表包含单列函数的错误,但在Powershell模块内部使用时要小心。由于作用域的工作方式,在-Merge
脚本块中,$Left
和$Right
变量将不可用(模块的变量是模块专用的,因此脚本块无法看到它们)。如果dot寻源或将函数直接包含在调用它的脚本中,这不是问题。@Omni,我在将cmdlet放入模块时做了一些测试,但无法确认您的问题。然而,在修改cmdlet的过程中,我发现了一个相当大的错误,如中所述。我创建了一个分支版本,粘贴在这个答案中。我怀疑这实际上是您遇到的问题(如果您能确认是否属实,我将不胜感激)。
. .\Join.ps1`
$reservations | LeftJoin $leases -On IP
IP MAC Name
-- --- ----
192.168.1.1 001D606839C2 Apple
192.168.1.2 00E018782BE1 Pear
192.168.1.3 0022192AF09C Banana
192.168.1.4 0013D4352A0D
$leases | select IP, NAME, @{N='MAC';E={$tmp=$_.IP;($reservations| ? IP -eq $tmp).MAC}}
$leases =
'IP,Name
192.168.1.1,Apple
192.168.1.2,Pear
192.168.1.3,Banana
192.168.1.99,FishyPC' | convertfrom-csv
$reservations =
'IP,MAC
192.168.1.1,001D606839C2
192.168.1.2,00E018782BE1
192.168.1.3,0022192AF09C
192.168.1.4,0013D4352A0D' | convertfrom-csv
$hashRes=@{}
foreach ($resRecord in $reservations) {
$hashRes[$resRecord.IP] = $resRecord
}
$leases | foreach {
$other = $hashRes[$_.IP]
[pscustomobject]@{IP=$_.IP
MAC=$other.MAC
Name=$_.name}
}
IP MAC Name
-- --- ----
192.168.1.1 001D606839C2 Apple
192.168.1.2 00E018782BE1 Pear
192.168.1.3 0022192AF09C Banana
192.168.1.99 FishyPC
Install-Module 'Join-Object'
Join-Object -Left $leases -Right $reservations -LeftJoinProperty 'IP' -RightJoinProperty 'IP'