在Powershell中,将两个表合并为一个表的最佳方法是什么?

Mic*_*ele 16 powershell scripting 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
Run Code Online (Sandbox Code Playgroud)

我有另一个从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
Run Code Online (Sandbox Code Playgroud)

为方便起见,我能够使用以下代码生成从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}}
    }
}
Run Code Online (Sandbox Code Playgroud)

所需的输出是这样的:

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
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法呢?

iRo*_*Ron 16

加入-对象

Join(别名Join-Object)函数可将来自两个物体的阵列的列到一个新的对象阵列(其可以被保存为一个表Join)或照原样使用.

Install-Script -Name Join
Run Code Online (Sandbox Code Playgroud)

句法

InnerJoin-Object

InnerJoin

Join-Object -JoinType Inner

命令

LeftJoin-Object(别名LeftJoin)函数是一个功能与几个别名联接两个表(每个由出的阵列的PSCustomObjects)相似于各个SQL加入指令.默认的连接类型Join-Object -JoinType Left.

  • RightJoin-Object(别名RightJoin)
    返回两个表中具有匹配值的记录.

  • Join-Object -JoinType Right(别名FullJoin-Object)
    返回左表中的所有记录和右表中的匹配记录.

  • FullJoin(别名Join-Object -JoinType Full)
    返回右表中的所有记录和右表中的匹配记录.

  • CrossJoin-Object(别名CrossJoin)
    返回左表或右表中匹配时的所有记录.

笔记

  1. 所有Join-Object -JoinType Cross命令都与PowerShell版本2及更高版本兼容.

参数

Update-ObjectUpdate

Join-Object -JoinType Left -Merge = {RightOrLeft.$_}Merge-Object参数定义左-右表进行连接.提供表有三种可能的语法:

  • 使用PowerShell管道: Merge

  • 在第一个参数位置提供数组中的两个表(用逗号分隔): Join-Object -JoinType Full -Merge = RightOrLeft.$_}

  • 为两个表提供命名参数: Install-Script -Name Join

笔记

  1. 如果只提供了一个表(),则将在表上执行自我联接..psm1

$env:PSModulePathImport-Module

Join(别名Join-Object)参数定义结果集指定如何连接表和在(内),以包括哪些行的条件.该 Join参数支持以下格式:

  • InnerJoin-Object 如果InnerJoin值为a Join-Object -JoinType Inner且提供了LeftJoin-Object参数,则由LeftJoin值定义的左列中的属性需要等于Join-Object -JoinType Left要包含在(内部)结果集中的值定义的右列中的属性.

  • RightJoin-Object或者RightJoin 如果该值是Join-Object -JoinType RightFullJoin-ObjectFullJoin参数类似于SQL Join-Object -JoinType Full子句.这意味着所有列出的属性需要相等(在左侧和右侧)才能包含在(内部)结果集中.列出的属性默认输出单个值(另请参见CrossJoin-Object).

  • CrossJoin 任何条件表达式Join-Object -JoinType Cross定义左行,Update-Object定义右行.

笔记

  1. Update类型具有最多的比较可能性,但比其他类型慢得多.

  2. 如果Join-Object -JoinType Left -Merge = {RightOrLeft.$_}省略参数或来自未知类型,则将执行交叉连接.

Merge-Object

定义应如何合并具有相同名称的特定列.该Merge参数接受以下类型:a Join-Object -JoinType Full -Merge = RightOrLeft.$_} 包含每列的特定合并表达式,或Install-Script -Name Join包含未定义合并表达式的所有列的默认合并表达式.
在表达式中的位置:

  • .psm1 保存每个列名称.
  • $env:PSModulePath保持左行并Import-Module保持右行.
  • Join保留每个左值并Join-Object保持每个正确的值.
  • Join保存当前左行索引并InnerJoin-Object保存当前右行索引.

笔记:

  1. 仅当左值(InnerJoin)和右值(Join-Object -JoinType Inner)都存在(包括值)时才执行表达式,LeftJoin-Object否则只返回退出值.

  2. 如果没有为列定义表达式,LeftJoin则使用表达式.这意味着将两个值(在数组中)分配给当前属性.

  3. 列的表达由定义的Join-Object -JoinType Left,RightJoin-Object和-On RightJoin是:Join-Object -JoinType Right ,并且只能通过在散列表中定义的列特异性表达被否决.这意味着将单个值(任一FullJoin-ObjectFullJoin不等于Join-Object -JoinType Full)分配给当前属性.

  4. 要使用列特定表达式定义默认表达式,请使用默认表达式的零长度键名称,例如CrossJoin-Object

例子

给出以下表格:

. .\Join.ps1
Run Code Online (Sandbox Code Playgroud)
$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
Run Code Online (Sandbox Code Playgroud)

更新服务列表(替换名称上的现有服务并添加新服务)

Install-Script -Name Join
Run Code Online (Sandbox Code Playgroud)

更新进程列表,仅插入具有更高CPU的进程

. .\Join.ps1
Run Code Online (Sandbox Code Playgroud)

有关最新CrossJoin版本,请参阅PowerShell库或项目站点:https://github.com/iRon7/Join-Object


Kei*_*ill 9

Lee Holmes写了一篇关于Join-Object函数博客文章,它可以满足您的需求.太糟糕了,它还没有内置到PowerShell中.


ili*_*ili 5

这也可以使用我的模块Join-Object来完成

Install-Module 'Join-Object'

Join-Object -Left $leases -Right $reservations -LeftJoinProperty 'IP' -RightJoinProperty 'IP'
Run Code Online (Sandbox Code Playgroud)

关于性能,我针对10万行的样本数据进行了测试:

  1. @js2010发布的哈希表示例在 8 秒内运行。
  2. Join-Object由我在14秒内跑完。
  3. LeftJoin作者:@iRon运行时间为 1 分 50 秒