簡體   English   中英

從powershell數組/集合/哈希表中刪除一行

[英]Remove a row from a powershell array/collection/hashtable

我有一個大型數組(從Excel電子表格導入),它有一個我要刪除的“總”行。 它始終是數組中的最后一項。 我試圖找到一種方法來刪除最后一個數組項,但不能。 以下數據和代碼示例:

$data = Import-XLSX -Path "C:\Pathtofile\spreadsheet.xlsx" -Sheet "SheetName" -RowStart 3
$data | ? {$_.Server -eq "Total"}


Server        : Total
VLAN          :
IP Address    :
CPU           : 84
RAM           : 313
C:\           : 2840
D:\           : 17950
OS Version    :
OS Edition    :
SQL Version   :
SQL Edition   :
Datastore     :
Reboot        :
Notes         :

我希望能夠從數組中刪除此行。 我嘗試過以下方法:

$data.Remove("Total")
Exception calling "Remove" with "1" argument(s): "Collection was of a fixed size."
At line:1 char:1
+ $ImportCSV.Remove("Total")
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : NotSupportedException

如果我檢查數組類型,我得到以下內容:

$data.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array

如果我像這樣重新鍵入對象,我得到以下內容:

$data = {$data}.Invoke()
$data.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Collection`1                             System.Object

$data.Remove("Total")
False

這不會刪除該項目。 我在這里錯過了什么?

數組在PowerShell中是不可變的,您無法添加或刪除它們中的元素。 你能做的是:

a)創建一個新數組並過濾你不想要的數組(例如使用-ne ):

$data = $data | ? {$_.Server -ne "Total"}

要么

b)按索引選擇最后一個元素的所有內容(可能是大數據庫上的資源,我不知道):

$data = $data[0..($data.Count-2)]

要么

c)將其轉換為[System.Collections.ArrayList] ,這是可變的,然后從中刪除一個元素:

$data = [System.Collections.ArrayList]$data
$data.RemoveAt($data.Count-1)

通過分析和背景信息補充TessellatingHeckler的有用答案

  • 如上所述, PowerShell數組(.NET類型[System.Object[]] )是固定大小的 - 您無法添加或刪除元素 (但是,您可以更改現有元素 )。

    • 當您使用++=將元素“添加”到PowerShell數組時,會在后台創建一個數組,這是原始數據的副本 (淺層克隆)。

    • 唯一的原因陣列具有.Add() .Remove().RemoveAt()方法是他們實現通用System.Collections.IList接口 ,它是由許多不同類型的集合,其中有一些實施調整大小。
      試圖在固定大小的集合(如數組)上調用這些方法會導致"Collection was of a fixed size." 你看到的錯誤信息。

  • 無論輸入集合的類型如何, 通過輸出多個對象的管道發送任何內容都將作為(新) 數組出現 (單個結果對象作為自身輸出,不包含在集合中。)

    • 因此,使用$data | ? {$_.Server -ne "Total"}等命令過濾掉集合的元素 $data | ? {$_.Server -ne "Total"} $data | ? {$_.Server -ne "Total"}創建一個總是數組集合( [System.Object[]] ,如果有超過1個輸出對象)。

為什么嘗試失敗

$data.Remove("Total") 從根本上失敗了,因為數組不支持刪除,如上所述。

但即使$data 可調整大小的集合(例如[System.Collections.ArrayList] ),傳遞"Total"也不會有效,因為您嘗試調用的IList.Remove方法要求您傳遞元素以移除自身在你的情況下,它將是.Server屬性包含"Total"對象 ,最容易作為$data[-1]訪問。

另請注意,傳遞不是列表元素的值是安靜的無操作(如果集合可調整大小)。

鑒於您想要刪除最后一個元素,基於索引的IList.RemoveAt方法將是更簡單的選擇。


{$data}.Invoke()確實執行了{$data}.Invoke()重新輸入 ,但是以最神秘的方式避免

乍一看, 從概念上講 ,該命令應該是一個無操作 :你只是在一個腳本塊{ ... } )中包含一個變量引用,然后你可以調用它,它應該只輸出變量的

不是無操作的原因 你繞過PowerShell對腳本塊的正常處理是通過.NET .Invoke()方法調用它而不是通常調用腳本塊的方式:使用call operator &

如果在腳本塊上使用.Invoke() ,則始終會獲得[System.Collections.ObjectModel.Collection[psobject]]實例(即使它只包含1個對象)。

相比之下,在幕后調用.Invoke()之后使用&執行額外的工作:如果集合只包含1個元素,則直接返回該元素(集合被解包)。 否則,集合將轉換為PowerShell數組( [System.Object[]] ;我不清楚此轉換的具體情況)。

既然你使用.Invoke()直接,你要調用.Remove()上運行[System.Collections.ObjectModel.Collection[psobject]]可調整大小,並有自己的.Remove()方法,其排除邏輯是一樣的就像IList.Remove() ,它會影響它。

但是,它與IList.Remove()不同之處在於返回反映刪除嘗試成功的[bool] ,這就是為什么你在第二次嘗試時得到false原因。

然而,與第一次嘗試不同的是,這次失敗不是基本的,並且傳入最后一個元素所包含的對象 (行); 類似地,具有最高索引的.RemoveAt()可以工作:

# Convert to [System.Collections.ObjectModel.Collection[psobject]]
$dataResizable = { $data }.Invoke()

# Remove last item by index.
$dataResizable.RemoveAt($dataResizable.Count-1)

# Alternative: Remove last item by object reference / value.
# Returns [bool], which we suppress.
$null = $dataResizable.Remove($dataResizable[-1])

所有這一切, 在腳本塊上使用.Invoke()只是為了得到一個可調整大小的集合是不明智的
相反,選擇TessellatingHeckler的答案中演示的方法之一。

此外, PSv5 +提供了一種從通過管道傳遞的集合中刪除最后一個元素的簡單方法, Select-Object -SkipLast 1

$data = Import-XLSX -Path "C:\Pathtofile\spreadsheet.xlsx" -Sheet "SheetName" -RowStart 3 |
  Select-Object -SkipLast 1

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM