【问题标题】:Fastest way to convert/process Datatable to Custom PSObject将数据表转换/处理为自定义 PSObject 的最快方法
【发布时间】:2017-03-09 00:10:58
【问题描述】:

我能够从 MySql 查询中填充数据表 $devices (例如)

PS C:\Users\MKANET\Desktop\dev\lab> $devices.table[10]

name                                    ip                                          mac                                    vendor
----                                    --                                          ---                                    ------
ComputerTest                            10.51.18.6                                  fd1969ff4cb9                           HewlettP

我想将该数据表类型转换为自定义 PSObject;其中,mac 列转换为 PSObject NoteProperty 名称“Mac-Address”;并且,将相应的值转换为 00-00-00-00 字符串格式:

PS C:\Users\MKANET\Desktop\dev\lab> $devices[1]

name                               ip                                      MAC-Address                             vendor
-------                            --                                      -----------                             ------------
ComputerTest                       10.51.18.6                              fd-19-69-ff-4c-b9                       HewlettP

考虑到这些数据表可能比较大(可能有几百行),我需要在 Powershell 中使用最快的处理方法。

如果它能使转换/修改过程显着加快,我很乐意将 $Devices 保留为数据表;仅将“mac”列的值修改/处理为:00-00-00-00-00-00 文本格式,永久

【问题讨论】:

    标签: mysql powershell datatable


    【解决方案1】:

    使用 Select-Object,它应该在 Powershell 中自动将 DataRow / DataTable 转换为 PSCustomObject。这是我将运行以转换为 PSCustomObject 并在一行中处理 MAC 地址格式的内容。这可以应用于特定索引处的单行(如示例代码)或应用于整个 DataTable 以转换为 PSObject 数组。

    MAC 地址格式会删除原始中的所有非字母数字字符,转换为小写,然后在适当的索引处插入连字符。

    $devices.table[10] | Select-Object name,ip,@{N="MAC-Address";E={((((($_.mac -replace '[^a-zA-Z0-9]','').ToLower().insert(2,"-")).insert(5,"-")).insert(8,"-")).insert(11,"-")).insert(14,"-")}},vendor
    

    【讨论】:

      【解决方案2】:

      让一些读者明白一点:在 PowerShell 中,DataTable 一个 PS 对象,只是一个具有 [System.Data.DataTable] 类型的对象。这种类型(类)提供了许多操作对象的方法,例如添加新列(如@e-z-hart 提供的答案所示)。

      将对象转换为通用的“PSObject”实际上意味着剥离与 [DataTable] 类相关的所有其他方法等,只留下一个简单的对象。你可以这样做:

      $obj = $devices.table[10] | foreach {
      
        $macaddress = ($_.mac -replace '(..)','$1-').TrimEnd("-")
      
        New-Object -TypeName PSObject -Property @{
          "name         = [System.String]        $_.name
          "ip"          = [System.Net.IPAddress] $_.ip
          "mac-address" = [System.String]        $macaddress
          "vendor"      = [System.String]        $_.vendor
        }
      }
      

      希望带有正则表达式的-replace 运算符比使用子字符串函数切分mac 地址更优雅一点(参见@e-z-hart 的回答)。有人可能会改进正则表达式,这样就不必在末尾修剪尾随的“-”。

      对于您提到的“几百”行,这应该非常快。

      请注意,对于奖励积分,'ip' 列被转换为 [System.Net.IPAddress] 类型,其中包括一个 ToString() 方法以我们通常看到的点分格式返回地址。我假设这是矫枉过正,所以你可能希望它始终是一个 [System.String]。

      最后,如果您真的希望 MAC-Address 列成为 NoteProperty,那么我将从 New-Object cmdlet 的属性列表中排除该列并使用 Add-Member。您可以将New-Object 的输出分配给一个变量,然后将其传递给Add-Member,或者尝试将New-Object 的输出通过管道传输到Add-Member 一次性完成:

      New-Object ... | Add-Member -MemberType NoteProperty -Name "Mac-Address" -Value $macaddress
      

      【讨论】:

        【解决方案3】:

        您可以使用表达式列将 MAC 列的格式化版本添加到您的数据表对象。可能有一种更优雅的方式来编写表达式,但这会起作用(我假设 $devices 是一个 DataTable):

        $maColumn = $devices.Columns.Add('MAC-Address')
        $maColumn.Expression = "SUBSTRING(mac, 1, 2) + '-' + SUBSTRING(mac, 3, 2) + '-' + SUBSTRING(mac, 5, 2) + '-' + SUBSTRING(mac, 7, 2) + '-' + SUBSTRING(mac, 9, 2) + '-' + SUBSTRING(mac, 11, 2)"
        

        【讨论】:

          猜你喜欢
          • 2010-10-01
          • 1970-01-01
          • 1970-01-01
          • 2013-05-16
          • 2019-07-15
          • 2016-07-02
          • 1970-01-01
          • 2011-03-15
          • 2019-06-23
          相关资源
          最近更新 更多