在PowerShell中,将两个表连接为一个表的最佳方式是什么?

人气:940 发布:2022-10-16 标签: 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          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 Core

Join-Object cmdlet显示以下代理命令及其自己的默认值(-JoinType-Property):

InnerJoin-Object(AliasInnerJoinJoin),组合相关对象 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-Objectcmdlet有两个版本(两个版本提供相同的功能):

Join Module

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 of paste (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)

,请提供

596