问题描述
我对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 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"字段就会填充该字段:
$reservations = $reservations | foreach {
$res = $_
$match = $leases | where {$_.IP -eq $res.IP} | select -unique
if ($match -ne $NULL) {
"" | select @{n="IP";e={$res.IP}}, @{n="MAC";e={$res.MAC}}, @{n="Name";e={$match.Name}}
}
}
所需输出如下所示:
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
有没有更好的办法?
推荐答案
一年半后,我粘贴在原始答案中的cmdlet经历了如此多次的更新,以至于它完全过时了。因此,我已将code和ReadMe替换为指向最新版本的链接。
Join-Object
根据两个对象列表之间的相关属性合并它们。
说明 组合一个或多个对象的特性。它创建一个集,该集可以另存为新对象或按原样使用。对象联接是一种通过使用每个对象列表共有的值来组合一个或多个对象列表中的属性的方法。
主要功能
直观(类似SQL)语法 智能财产合并 用于更新、合并和特定联接类型的预定义联接命令 (左)输入对象和输出对象的定义良好的管道(正确使用时保留内存) 在大型对象列表上的执行速度比比较对象快约40% 支持输入的(自定义)对象、数据表和词典(例如哈希表) 智能属性和计算属性表达式 自定义关系表达式 轻松安装(点采购) 支持PowerShell for Windows(5.1)和PowerShell CoreJoin-Object cmdlet显示以下代理命令及其自己的默认值(-JoinType
和-Property
):
InnerJoin-Object
(AliasInnerJoin
或Join
),组合相关对象
LeftJoin-Object
(AliasLeftJoin
),合并相关对象并添加剩余对象
RightJoin-Object
(AliasRightJoin
),组合相关对象并添加其余正确的对象
FullJoin-Object
(AliasFullJoin
),合并相关对象并添加其余的左对象和右对象
CrossJoin-Object
(AliasCrossJoin
),将每个左对象与每个右对象组合
Update-Object
(AliasUpdate
),用相关的右对象更新左对象
Merge-Object
(AliasMerge
),用相关的右对象更新Left对象,并添加其他新的(不相关的)右对象
ReadMe
完整的自述文件(和源代码)可从GitHub获得:https://github.com/iRon7/Join-Object
安装
此Join-Object
cmdlet有两个版本(两个版本提供相同的功能):
Install-Module -Name JoinModule
Join Script
Install-Script -Name Join
(或将Join.psm1
模块重命名为Join.ps1
脚本文件)
并由dot sourcing调用脚本:
. .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
性能
绩效测评:
PowerShell管道设计为串流对象(以保护内存),这意味着输入对象的两个?列表通常不(不应该)驻留在内存中。通常,它们是从其他地方(例如远程服务器、磁盘)检索的。此外,输出通常重要其中linq
解决方案速度很快,但可能很容易使您在得出结论时处于错误的位置,因为linq
字面上的推迟执行(lazy evaluation),另请参阅:fastest way to get a uniquely index item from the property of an array。
换句话说,如果要(衡量)PowerShell的性能,重要的是看一下完整的端到端解决方案,它更可能类似于:
import-csv .eservations.csv |LeftJoin (import-csv .leases.csv) -On IP |Export-Csv .esults.csv
(1)注意:遗憾的是,没有简单的方法来构建并行输入流(请参阅:#15206
Deferred input pipelines)
(更多)示例
在相关的堆栈溢出问题中可以找到更多示例:
Combining Multiple CSV Files Combine two CSVs - Add CSV as another Column CMD or Powershell command to combine (merge) corresponding lines from two files Can I use SQL commands (such as join) on objects in powershell, without any SQL server/database involved? CMD or Powershell command to combine (merge) corresponding lines from two files Compare Two CSVs, match the columns on 2 or more Columns, export specific columns from both csvs with powershell Merge two CSV files while adding new and overwriting existing entries Merging two CSVs and then re-ordering columns on output Merge two CSV files while adding new and overwriting existing entries Efficiently merge large object datasets having multiple matching keys Is there a PowerShell equivalent ofpaste
(i.e., horizontal file concatenation)?
combine (merge) corresponding lines from two files
和Join-Object test script。
如果您支持Add a Join-Object cmdlet to the standard PowerShell equipment (#14994
)