关于数组

简短说明

描述数组,数组是旨在存储项集合的数据结构。

详细描述

数组是一种数据结构,旨在存储项目集合。 这些项可以是相同类型或不同类型的。

从 Windows PowerShell 3.0 开始,零个或一个对象的集合具有数组的某些属性。

创建和初始化数组

要创建和初始化数组,请为变量分配多个值。 数组中存储的值用逗号分隔,并由赋值运算符 (=) 与变量名称分隔。

例如,要创建一个名为 $A 的数组,其中包含 22、5、10、8、12、9 和 80 这七个数字 (int) 值,请键入:

$A = 22,5,10,8,12,9,80

您还可以使用范围运算符 (..) 创建和初始化数组。 例如,要创建并初始化包含值 5 到 8 的名为 “$B” 的数组,请键入:

$B = 5..8

因此,$B 包含四个值:5、6、7 和 8。

如果未指定数据类型,PowerShell 会将每个数组创建为对象数组(类型:System.Object[])。 要确定数组的数据类型,请使用 GetType() 方法。 例如,要确定 $a 数组的数据类型,请键入:

$a.GetType()

要创建强类型数组(即只能包含特定类型值的数组),请将变量强制转换为数组类型,例如 string[]、long[] 或 int32[]。 若要强制转换数组,请在变量 name 前面加上用方括号括起来的数组类型。 例如,要创建一个名为 $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 子表达式运算符创建一个数组,即使它包含零个或一个对象。

数组运算符的语法如下:

@( ... )

您可以使用 array 运算符创建包含零个或一个对象的数组。 例如:

PS> $a = @("Hello World")
PS> $a.Count
1
PS> $b = @()
PS> $b.Count
0

数组运算符在脚本中特别有用,当您要获取对象,但不知道将获得多少个对象时。 例如:

$p = @(Get-Process Notepad)

有关 array 子表达式运算符的更多信息,请参阅 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

您可以使用索引的 range 运算符检索数组的一部分。 例如,要检索数组的第二个到第五个元素,您可以键入:

$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

此外,要列出多个范围和单个元素,您可以使用 plus 运算符。 例如,要列出元素 0 到 2、4 到 6 以及第 8 个位置的元素类型:

$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 property 或其 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(脚本块表达式)

ForEach(脚本块表达式,object[] 参数)

注释

该语法需要使用脚本块。 括号是可选的。

下面的示例演示如何使用 foreach 方法。 在这种情况下,目的是生成数组中元素的平方值。

请注意,此方法是在 PowerShell v4 中添加的,在低于此方法的版本中不可用。 对于以前的版本,请使用 ForEach-Object Cmdlet 的 Pipelining 方法

$a = @(0 .. 3)
$a.ForEach({ $_ * $_})
0
1
4
9

就像 的-ArgumentList参数一样ForEach-Object,该arguments参数允许将参数数组传递给配置为接受参数的脚本块。

ForEach(类型 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(字符串 propertyName)

ForEach(字符串 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(字符串 methodName)

ForEach(字符串 methodName, object[] 参数)

最后, ForEach 方法可用于对集合中的每个项目执行方法。

("one", "two", "three").ForEach("ToUpper")
ONE
TWO
THREE

就像 的-ArgumentList参数一样ForEach-Object,该arguments参数允许将参数数组传递给配置为接受参数的脚本块。

注释

从 Windows PowerShell 3.0 开始,检索集合中每个项的属性和执行方法也可以使用“标量对象和集合的方法”来完成,您可以在此处阅读更多相关信息 about_methods

位置

允许筛选或选择数组的元素。 脚本的计算结果必须为以下值:零 (0)、空字符串, $false 或者 $null 元素显示在 Where

该方法 Where 有一个定义。

Where(scriptblock expression[, WhereOperatorSelectionMode mode
                            [, int numberToReturn]])

Expression筛选所需的 is 脚本块,modeoptional 参数允许其他选择功能,optional numberToReturn 参数允许限制从筛选器返回的项目数。

注释

该语法需要使用脚本块。 括号是可选的。

以下示例演示如何从数组中选择所有奇数。

(0..9).Where{ $_ % 2 }
1
3
5
7
9

以下选择模式可用。

违约

Default 模式使用 Expression scriptblock 筛选项目。

如果提供 a 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

注释

Until两者都SkipUntil在不测试一批项目的前提下运行。

Until 返回 BEFORE the first pass 的项目。

SkipUntil返回第一次传递之后的所有项目,包括第一个传递的项目。

分裂

Split 模式将集合项拆分或分组为两个单独的集合。 传递 scriptblock 表达式的函数和不传递 scriptblock 表达式的函数。

如果指定了 a numberToReturn ,则第一个集合将包含 传递 的项,但不得超过指定的值。

其余对象,甚至是那些 PASS 表达式 filter 的对象,都将在第二个集合中返回。

$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 返回数组的成员。

例如,以下命令获取 array 变量的成员 $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 方法来更改值。 以下示例将数组的 $a 第二个值(索引位置 1)更改为 500:

$a.SetValue(500,1)

您可以使用 += 运算符将元素添加到数组中。 下面的示例演示如何将元素添加到数组中 $a

$a = @(0..4)
$a += 5

注释

当您使用运算符 += 时,PowerShell 实际上会使用原始数组的值和添加的值创建一个新数组。 如果作重复多次或数组大小太大,这可能会导致性能问题。

从数组中删除元素并不容易,但您可以创建一个仅包含现有数组的选定元素的新数组。 例如,要创建 $t 包含数组中 $a 除索引位置 2 处的值之外的所有元素的数组,请键入:

$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,但分配值 NAME $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

另请参阅