我目前正在學習 PowerShell,從基礎開始,我已經開始學習陣列。更具體地說,回圈陣列。我注意到在單獨宣告一個陣列時,它只是簡單地寫成
$myarray = 1, 2, 3, 4, 5
然而,當宣告一個陣列是為了回圈它時,它被寫成
$myarray = @(1, 2, 3, 4, 5)
出于好奇,我嘗試運行代碼以在帶和不帶 @ 符號的情況下回圈遍歷陣列,只是為了看看它是否可以作業,并且它以完全相同的方式顯示在我為兩者創建的字串中。
我的問題是@符號的目的是什么?我嘗試查找它,但找不到任何結果。
uj5u.com熱心網友回復:
你要找的檔案上的操作員不僅包括了@,但(并)太-他們一起做了@(),也被稱為該陣列子運算式運算子。
它確保您包裝在其中的任何管道或運算式的輸出都是陣列。
要理解為什么這很有用,我們需要了解 PowerShell 傾向于扁平化陣列!讓我們用一個簡單的測驗函式來探索這個概念:
function Test-PowerShellArray {
param(
$Count = 2
)
while($count--){
Get-Random
}
}
這個函式將輸出一些亂數 -$Count確切地說是數字:
PS ~> Test-PowerShellArray -Count 5
652133605
1739917433
1209198865
367214514
1018847444
讓我們看看當我們要求 5 個數字時我們得到什么型別的輸出:
PS ~> $numbers = Test-PowerShellArray -Count 5
PS ~> $numbers.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
好的,所以我們存盤的結果輸出$numbers是型別[Object[]]- 這意味著我們有一個 適合型別物件的陣列Object(.NET 型別系統中的任何型別最終都繼承自Object,所以它實際上只是意味著我們有一個陣列“東西”,它可以包含任何東西)。
我們可以用不同的計數再試一次,得到相同的結果:
PS ~> $numbers = Test-PowerShellArray -Count 100
PS ~> $numbers.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
到目前為止一切順利 - 我們從一個函式中收集了多個輸出值并最終得到一個陣列,一切都如預期的那樣。
但是當我們只從函式中輸出 1 個數字時會發生什么:
PS ~> $numbers = Test-PowerShellArray -Count 1
PS ~> $numbers.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Int32 System.ValueType
說什么?現在我們得到System.Int32- 這是單個整數值的型別 - PowerShell 注意到我們只收到 1 個輸出值,然后“只有 1?我不會把它包裝在一個陣列中,你可以按原樣”
正是出于這個原因,您可能想要包裝您打算回圈的輸出(或以其他方式使用,要求它是一個陣列):
PS ~> $numbers = Test-PowerShellArray -Count 1
PS ~> $numbers.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Int32 System.ValueType
PS ~> $numbers = @(Test-PowerShellArray -Count 1) # @(...) saves the day
PS ~> $numbers.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
uj5u.com熱心網友回復:
這是宣告靜態陣列的另一種語法,但有一些關鍵細節可以理解它們之間的語法差異。
@()是陣列子運算式 operator。這與組運算式運算子 ()或子運算式運算子的 作業方式類似,$()但強制回傳的任何內容都為陣列,即使僅回傳 0 或 1 個元素。這可以在需要陣列或集合型別的任何地方行內使用。有關這些運算子的更多資訊,請閱讀PowerShell 檔案中的特殊運算子。
這1, 2, 3, 4是串列運算式語法,可以在需要陣列的任何地方使用。它在功能上@(1, 2, 3, 4)與陣列子運算式運算子等效,但在行為上有所不同。
@( Invoke-SomeCmdletOrExpression ) 將強制回傳的值是一個陣列,即使運算式只回傳 0 或 1 個元素。
# Array sub-expression
$myArray = @( Get-Process msedge )
請注意,這不必是單個 cmdlet 呼叫,它可以是任何運算式,利用您認為合適的管道。例如:
# We have an array of fruit
$fruit = 'apple', 'banana', 'apricot', 'cherry', 'a tomato ;)'
# Fruit starting with A
$fruitStartingWithA = @( $fruit | Where-Object { $_ -match '^a' } )
$fruitStartingWithA 應該回傳以下內容:
apple
apricot
a tomato ;)
還有另一種強制陣列型別的方法,我看到它經常在 Stack Overflow 上被提及為一個很酷的技巧(確實如此),但關于其行為的背景關系卻很少。
您可以使用 list-expression 語法的一個怪癖來強制陣列型別,但是這與使用陣列子運算式運算子之間有兩個主要區別。用逗號前綴運算式或變數,將強制回傳一個陣列,但兩者之間的行為會發生變化。考慮以下示例:
# Essentially the same as @( $someVar )
$myArray1 = , $someVar
# This behaves differently, read below
$myArray2 = , ( Invoke-SomeCmdletOrExpression )
@()或者在變數前面加上,will flatten (這里經常使用的另一個詞是unroll)將結果元素放入單個陣列中。但是對于運算式,如果您使用逗號前綴技巧,則必須使用 group-expression 運算子。由于分組運算式的解釋方式,您最終將得到一個由一個元素組成的陣列。
在這種情況下,它不會展平任何結果元素。
考慮Get-Process上面的例子。如果您msedge正在運行三個行程,$myArray.Count將顯示計數為 3,您可以使用 array-index 訪問器訪問各個行程$myArray[$i]。但是,如果您$myArray2在上面的第二個串列運算式示例中執行相同操作,$myArray2.Count將回傳計數 1。這實際上現在是一個具有單個元素的多維陣列。要獲取單個行程,您現在需要$myArray2[0].Count獲取行程計數,并使用陣列索引訪問器兩次來獲取單個行程:
$myArray2 = , ( Get-Process msedge )
$myArray2.Count # ======> 1
# I have 32 Edge processes right now
$myArray2[0].Count # ===> 32
# Get only the first msedge process
$myArray[0][0] # =======> Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
# =======> ------- ------ ----- ----- ------ -- -- -----------
# =======> 430 19 101216 138968 74.52 3500 1 msedge
起初這可能不清楚,因為列印$myArray2到輸出流將顯示與$myArray第一個示例和$myArray1第二個示例相同的輸出結果。
In short, you want to avoid using the comma-prefix trick when you want to use an expression, and instead use the array sub-expression @() operator as this is what it is intended for.
Note: There will be times when you want to define a static array of arrays but you will be using list-expression syntax anyways, so the comma-prefix becomes redundant. The only counterpoint here is if you want to create an array with an array in the first element to add more arrays to it later, but you should be using a generic
List[T]or anArrayListinstead of relying on one of the concatenation operators to expand an existing array (or=are almost always bad ideas on non-numeric types).
Here is some more information about arrays in PowerShell, as well as the Arrays specification for PowerShell itself.
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/315520.html
上一篇:C 反轉字串但先列印數字
