关于数组
简短说明
描述数组,这些数组是设计用于存储项集合的数据结构。
详细说明
数组是用于存储项集合的数据结构。 项可以是相同类型或不同的类型。
从 Windows PowerShell 3.0 开始,零个或一个 对象的集合具有数组的某些属性。
创建和初始化数组
若要创建和初始化数组,请将多个值分配给一个变量。 存储在数组中的值用逗号分隔,并通过赋值运算符 (=) 与变量名称分隔。
例如,若要创建一个名为 $A 的数组,其中包含 7 个数值 (int) 值 22、5、10、8、12、9 和 80,请键入:
$A = 22,5,10,8,12,9,80
还可以使用范围运算符 ( 创建和初始化数组。) 。 例如,若要创建并初始化名为“$B”且包含值 5 到 8 的数组,请键入:
$B = 5..8
因此,$B包含四个值:5、6、7 和 8。
如果未指定数据类型,PowerShell 将每个数组创建为对象数组, (类型:System.Object[]) 。 若要确定数组的数据类型,请使用 GetType () 方法。 例如,若要确定$a数组的数据类型,请键入:
$a.GetType()
若要创建强类型数组,即只能包含特定类型的值的数组,请将变量强制转换为数组类型,例如 string[]、long[]或 int32[]。 若要强制转换数组,请在变量名称前面加上括在方括号中的数组类型。 例如,若要创建一个名为 $ia 的 32 位整数数组,其中包含四个整数 (1500、2230、3350 和 4000) ,请键入:
[int32[]]$ia = 1500,2230,3350,4000
因此,$ia数组只能包含整数。
可以在 Microsoft .NET Framework中创建强制转换为任何受支持的类型的数组。 例如,Get-Process 检索以表示进程的对象属于 System.Diagnostics.Process 类型。 若要创建进程对象的强类型数组,请输入以下命令:
[Diagnostics.Process[]]$zz = Get-Process
数组子表达式运算符
即使数组包含零个或一个对象,数组子表达式运算符也会创建一个数组。
数组运算符的语法如下所示:
@( ... )
可以使用 array 运算符创建包含零个或一个对象的数组。 例如:
PS> $a = @("Hello World")
PS> $a.Count
1
PS> $b = @()
PS> $b.Count
0
获取对象时,数组运算符在脚本中特别有用,但不知道将获得多少个对象。 例如:
$p = @(Get-Process Notepad)
有关数组子表达式运算符的详细信息,请参阅 about_Operators。
访问和使用数组元素
读取数组
可以使用数组的变量名称来引用数组。 若要显示数组中的所有元素,请键入数组名称。 例如,假设 $a
是包含整数 0、1、2 的数组,直到 9;键入:
$a
0
1
2
3
4
5
6
7
8
9
可以使用从位置 0 开始的索引来引用数组中的元素。 将索引号括在方括号中。 例如,若要显示数组中的 $a
第一个元素,请键入:
$a[0]
0
若要显示数组中的第三个 $a
元素,请键入:
$a[2]
2
可以使用索引的范围运算符检索数组的一部分。 例如,若要检索数组的第二到第五个元素,请键入:
$a[1..4]
1
2
3
4
从数组末尾算起的负数。 例如,“-1”是指数组的最后一个元素。 若要按索引升序显示数组的最后三个元素,请键入:
$a = 0 .. 9
$a[-3..-1]
7
8
9
如果按降序键入负索引,输出将更改。
$a = 0 .. 9
$a[-1..-3]
9
8
7
但是,使用此表示法时要小心。 表示法从结束边界到数组开头的周期。
$a = 0 .. 9
$a[2..-2]
2
1
0
9
8
此外,一个常见的错误是假设 $a[0..-2]
引用数组的所有元素,最后一个元素除外。 它引用数组中的第一个、最后一个和倒数第二的元素。
可以使用加号运算符 (+) 将范围与数组中的元素列表组合在一起。 例如,若要在索引位置 0、2 和 4 到 6 处显示元素,请键入:
$a = 0 .. 9
$a[0,2+4..6]
0
2
4
5
6
此外,若要列出多个范围和单个元素,可以使用加号运算符。 例如,若要列出零到二、四到六的元素,以及第八个位置类型的元素:
$a = 0..9
$a[+0..2+4..6+8]
0
1
2
4
5
6
8
对数组元素的迭代
还可以使用循环构造(如 ForEach、For 和 While 循环)来引用数组中的元素。 例如,若要使用 ForEach 循环显示数组中的 $a
元素,请键入:
$a = 0..9
foreach ($element in $a) {
$element
}
0
1
2
3
4
5
6
7
8
9
Foreach 循环循环访问数组,并返回数组中的每个值,直到到达数组的末尾。
当你在检查数组中的元素时递增计数器时,For 循环非常有用。 例如,若要使用 For 循环返回数组中的每个其他值,请键入:
$a = 0..9
for ($i = 0; $i -le ($a.length - 1); $i += 2) {
$a[$i]
}
0
2
4
6
8
可以使用 While 循环显示数组中的元素,直到定义的条件不再为 true。 例如,若要在数组索引小于 4 时显示数组中的 $a
元素,请键入:
$a = 0..9
$i=0
while($i -lt 4) {
$a[$i];
$i++
}
0
1
2
3
数组的属性
Count 或 Length 或 LongLength
若要确定数组中的项数,请使用 Length
属性或其 Count
别名。 Longlength
如果数组包含超过 2,147,483,647 个元素,则非常有用。
$a = 0..9
$a.Count
$a.Length
10
10
级别
返回数组中的维数。 PowerShell 中的大多数数组只有一个维度。 即使你认为正在构建多维数组;如以下示例所示:
$a = @(
@(0,1),
@("b", "c"),
@(Get-Process)
)
[int]$r = $a.Rank
"`$a rank: $r"
$a rank: 1
在 PowerShell 中构建真正的多维数组需要 .Net Framework 的帮助。 如以下示例所示:
[int[,]]$rank2 = [int[,]]::new(5,5)
$rank2.rank
2
数组的方法
清除
将所有元素值设置为数组的元素类型的 默认值 。 Clear () 方法不会重置数组的大小。
在以下示例 $a
中是 对象的数组。
$a = 1, 2, 3
$a.Clear()
$a | % { $null -eq $_ }
True
True
True
在此示例中, $intA
显式类型化为包含整数。
[int[]] $intA = 1, 2, 3
$intA.Clear()
$intA
0
0
0
ForEach
允许循环访问数组中的所有元素,并为数组的每个元素执行给定的操作。
ForEach 方法具有多个执行不同操作的重载。
ForEach(scriptblock expression)
ForEach(type convertToType)
ForEach(string propertyName)
ForEach(string propertyName, object[] newValue)
ForEach(string methodName)
ForEach(string methodName, object[] arguments)
ForEach(scriptblock expression, object[] arguments)
ForEach (scriptblock 表达式)
ForEach (scriptblock 表达式,object[] 参数)
注意
语法需要使用脚本块。 括号是可选的。
以下示例演示如何使用 foreach 方法。 在这种情况下,目的是生成数组中元素的平方值。
请注意,此方法已添加到 PowerShell v4 中,在以下版本中不可用。 对于以前的版本,请将 Pipelining 方法用于 ForEach-Object Cmdlet
$a = @(0 .. 3)
$a.ForEach({ $_ * $_})
0
1
4
9
与 的 ForEach-Object
参数一样-ArgumentList
, arguments
参数允许将参数数组传递给配置为接受它们的脚本块。
ForEach (type convertToType)
方法 ForEach
可用于快速将元素转换为其他类型;下面的示例演示如何将字符串日期列表转换为 [DateTime]
类型。
@("1/1/2017", "2/1/2017", "3/1/2017").ForEach([datetime])
Sunday, January 1, 2017 12:00:00 AM
Wednesday, February 1, 2017 12:00:00 AM
Wednesday, March 1, 2017 12:00:00 AM
ForEach (string propertyName)
ForEach (string propertyName, object[] newValue)
方法 ForEach
还可用于快速检索或设置集合中每个项的属性值。
# Set all LastAccessTime properties of files to the current date.
(dir 'C:\Temp').ForEach('LastAccessTime', (Get-Date))
# View the newly set LastAccessTime of all items, and find Unique entries.
(dir 'C:\Temp').ForEach('LastAccessTime') | Get-Unique
Wednesday, June 20, 2018 9:21:57 AM
ForEach (string methodName)
ForEach (string methodName, object[] 参数)
最后, ForEach
方法可用于对集合中的每个项执行方法。
("one", "two", "three").ForEach("ToUpper")
ONE
TWO
THREE
与 的 ForEach-Object
参数一样-ArgumentList
, arguments
参数允许将参数数组传递给配置为接受参数的脚本块。
注意
从 Windows PowerShell 3.0 开始,还可以使用“标量对象和集合的方法”完成检索集合中每个项的属性和执行方法,可在此处阅读有关此的详细信息about_methods
其中
允许筛选或选择数组的元素。 脚本的计算结果必须不同于以下值:零 (0) 、空字符串或 $false
$null
要在 之后显示的元素 Where
方法有一个定义 Where
。
Where(scriptblock expression[, WhereOperatorSelectionMode mode
[, int numberToReturn]])
Expression
筛选所需的 is scriptblock,mode
可选参数允许其他选择功能,可选numberToReturn
参数允许限制从筛选器返回的项数。
注意
语法需要使用脚本块。 括号是可选的。
以下示例演示如何从数组中选择所有奇数。
(0..9).Where{ $_ % 2 }
1
3
5
7
9
以下选择模式可用。
Default
模式 Default
使用 Expression
scriptblock 筛选项。
如果提供了 , numberToReturn
则指定要返回的最大项数。
# Get the zip files in the current users profile, sorted by LastAccessTime.
$Zips = dir $env:userprofile -Recurse '*.zip' | Sort-Object LastAccessTime
# Get the least accessed file over 100MB
$Zips.Where({$_.Length -gt 100MB}, 'Default', 1)
注意
Default
模式和First
模式都返回第一个 (numberToReturn
) 项,并且可以互换使用。
上一个
$h = (Get-Date).AddHours(-1)
$logs = dir 'C:\' -Recurse '*.log' | Sort-Object CreationTime
# Find the last 5 log files created in the past hour.
$logs.Where({$_.CreationTime -gt $h}, 'Last', 5)
SkipUntil
该 SkipUntil
模式跳过集合中的所有对象,直到对象通过脚本块表达式筛选器。 然后,它返回 所有 剩余的收集项,而无需对其进行测试。 仅测试一个通过的项目
这意味着返回的集合将包含尚未测试 的传递 项 和非通过 项。
可以通过将值传递给 numberToReturn
参数来限制返回的项数。
$computers = "Server01", "Server02", "Server03", "localhost", "Server04"
# Find the first available online server.
$computers.Where({ Test-Connection $_ }, 'SkipUntil', 1)
localhost
截止
模式 Until
反转 SkipUntil
模式。 它返回集合 中的所有项, 直到项通过脚本块表达式。 一旦项 通过 scriptblock 表达式,该方法 Where
将停止处理项。
这意味着你将从 Where
方法收到第一组未传递的项。 一个项目通过后,其余项将不进行测试,也不会返回。
可以通过将值传递给 numberToReturn
参数来限制返回的项数。
# Retrieve the first set of numbers less than or equal to 10.
(1..50).Where({$_ -gt 10}, 'Until')
# This would perform the same operation.
(1..50).Where({$_ -le 10})
1
2
3
4
5
6
7
8
9
10
注意
和 SkipUntil
都在Until
不测试一批项的前提下运行。
Until
返回第一次传递之前的项。
SkipUntil
返回第一个传递之后的所有项,包括第一个传递项。
拆分
该 Split
模式将集合项拆分或分组为两个单独的集合。 传递 scriptblock 表达式的和不传递脚本块表达式的。
如果指定了 ,则第一个 numberToReturn
集合将包含 传递 的项,而不是超过指定的值。
其余对象(即使是 传递 表达式筛选器的对象)将在第二个集合中返回。
$running, $stopped = (Get-Service).Where({$_.Status -eq 'Running'}, 'Split')
$running
Status Name DisplayName
------ ---- -----------
Running Appinfo Application Information
Running AudioEndpointBu... Windows Audio Endpoint Builder
Running Audiosrv Windows Audio
...
$stopped
Status Name DisplayName
------ ---- -----------
Stopped AJRouter AllJoyn Router Service
Stopped ALG Application Layer Gateway Service
Stopped AppIDSvc Application Identity
...
获取数组的成员
若要获取数组的属性和方法(如 Length 属性和 SetValue 方法),请使用 Get-Member cmdlet 的 InputObject 参数。
通过管道将数组传递给 Get-Member
时,PowerShell 一次发送一个项,并 Get-Member
返回数组中每个项的类型, (忽略重复项) 。
使用 -InputObject 参数时, Get-Member
返回数组的成员。
例如,以下命令获取数组变量的成员 $a
。
Get-Member -InputObject $a
还可以通过在传递给 Get-Member cmdlet 的值之前键入逗号 (,) 来获取数组的成员。 逗号使数组成为数组中的第二项。 Windows PowerShell一次传递一个数组,Get-Member 返回数组的成员。 就像接下来的两个示例一样。
,$a | Get-Member
,(1,2,3) | Get-Member
操作数组
可以更改数组中的元素,将元素添加到数组,并将两个数组中的值合并到第三个数组中。
若要更改数组中特定元素的值,请指定要更改的元素的数组名称和索引,然后使用赋值运算符 (=) 为元素指定新值。 例如,若要将数组中 $a
第二项的值 (索引位置 1) 更改为 10,请键入:
$a[1] = 10
还可以使用数组的 SetValue 方法更改值。 以下示例将数组 (索引位置 1) 的第二个 $a
值更改为 500:
$a.SetValue(500,1)
可以使用 += 运算符将元素添加到数组。 以下示例演示如何向数组添加元素 $a
。
$a = @(0..4)
$a += 5
注意
使用 +=
运算符时,PowerShell 实际上会创建一个具有原始数组值和附加值的新数组。 如果重复多次操作或数组大小太大,这可能会导致性能问题。
从数组中删除元素并不容易,但可以创建仅包含现有数组的选定元素的新数组。 例如,若要使用数组中的所有$a
元素(索引位置 2 处的值除外)创建$t
数组,请键入:
$t = $a[0,1 + 3..($a.length - 1)]
若要将两个数组合并为单个数组,请使用加号运算符 (+) 。 以下示例创建两个数组,将它们组合在一起,然后显示生成的组合数组。
$x = 1,3
$y = 5,9
$z = $x + $y
因此, $z
数组包含 1、3、5 和 9。
若要删除数组,请将 $null 的值分配给该数组。 以下命令删除 变量中的 $a
数组。
$a = $null
也可以使用 Remove-Item
cmdlet,但赋值 $null
速度更快,尤其是对于大型数组。
零或 1 的数组
从 Windows PowerShell 3.0 开始,零个或一个 对象的集合具有 Count 和 Length 属性。 此外,还可以索引到一个对象的数组中。 此功能可帮助你避免在需要集合的命令获得少于两个项时发生的脚本错误。
以下示例演示此功能。
零个对象
$a = $null
$a.Count
$a.Length
0
0
一个 对象
$a = 4
$a.Count
$a.Length
$a[0]
$a[-1]
1
1
4
4