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

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

我是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”字段,就会填充该字段:

所需的输出如下所示:

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核心
可以使用以下命令从PowerShell Gallery下载Join Object cmdlet:

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

  • InnerJoin对象
    (别名
    InnerJoin
    Join
    ),组合相关对象
  • LeftJoin对象
    (别名
    LeftJoin
    ),组合相关对象并添加其余的左对象
  • RightJoin对象
    (别名
    RightJoin
    ),组合相关对象并添加其余的右对象
  • FullJoin对象
    (别名
    FullJoin
    ),组合相关对象并添加其余的左、右对象
  • CrossJoin对象
    (别名
    CrossJoin
    ),将每个左对象与每个右对象组合在一起
  • 更新对象
    (别名
    更新
    ),用相关的右对象更新左对象
  • Merge Object
    (别名
    Merge
    ),用相关的右对象更新左对象,并添加其余新的(不相关的)右对象
完整的自述文件(和源代码)可从GitHub获得:

装置 此
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行的样本数据进行了测试:

  • 哈希表示例由run在8秒内发布
  • 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'