about_Arrays

简短说明

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

详细说明

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

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

创建和初始化数组

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

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

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

逗号还可用于通过将逗号放在单个项之前来初始化单个项数组。

例如,若要创建一个名为 的项数组 $B ,其中包含单个值 7,请键入:

$B = ,7

此外,还可使用范围运算符创建和初始化数组 .. () 。 以下示例创建一个数组,其中包含值 5 到 8。

$C = 5..8

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

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

$A.GetType()

若要创建强类型数组(即只能包含特定类型的值的数组),请强制将变量强制为数组类型,例如 string[] 、long[]int32[]。 若要强制转换数组,请用括在括号中的数组类型在变量名称之前。 例如,若要创建一个名为 的 32 位整数数组,其中包含四个整数 $ia (1500、2230、3350 和 4000) ,请键入:

[int32[]]$ia = 1500,2230,3350,4000

因此,数组 $ia 只能包含整数。

可以创建强制转换到 .NET 中任何受支持类型的数组。 例如,为表示进程而检索 Get-Process 的对象是 System.Diagnostics.Process 类型。 若要创建进程对象的强类型数组,请输入以下命令:

[Diagnostics.Process[]]$zz = Get-Process

数组子表达式运算符

数组子表达式运算符从数组内的语句创建数组。 无论 运算符中的 语句生成什么,运算符都会将语句放在数组中。 即使存在零个或一个对象。

数组运算符的语法如下所示:

@( ... )

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

$a = @("Hello World")
$a.Count
1
$b = @()
$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

此外,若要列出多个范围和单个元素,可以使用加号运算符。 例如,列出元素 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 属性或其 Count 别名。 如果数组包含的元素超过 2,147,483,647,则 Longlength 非常有用。

$a = 0..9
$a.Count
$a.Length
10
10

Rank

返回数组中的维数。 PowerShell 中的大多数数组只有一个维度。 即使你认为要生成多维数组,如以下示例所示:

$a = @(
  @(0,1),
  @("b", "c"),
  @(Get-Process)
)

"`$a rank: $($a.Rank)"
"`$a length: $($a.Length)"
"`$a length: $($a.Length)"
"Process `$a[2][1]: $($a[2][1].ProcessName)"

本示例将创建包含其他数组的一维数组。 这也称为锯 齿数组Rank 属性证明这是一维的。 若要访问锯齿数组中的项,索引必须位于单独的括号 [] () 。

$a rank: 1
$a length: 3
$a[2] length: 348
Process $a[2][1]: AcroRd32

多维数组按行 主序存储。 下面的示例演示如何创建真正的多维数组。

[string[,]]$rank2 = [string[,]]::New(3,2)
$rank2.rank
$rank2.Length
$rank2[0,0] = 'a'
$rank2[0,1] = 'b'
$rank2[1,0] = 'c'
$rank2[1,1] = 'd'
$rank2[2,0] = 'e'
$rank2[2,1] = 'f'
$rank2[1,1]
2
6
d

若要访问多维数组中的项,请用逗号分隔索引, () 一组括号内 , [] () 。

对多维数组执行某些操作(如复制和串联)需要平展该数组。 平展将数组转换为无约束类型的一维数组。 生成的数组按行主序处理所有元素。 请看下面的示例:

$a = "red",$true
$b = (New-Object 'int[,]' 2,2)
$b[0,0] = 10
$b[0,1] = 20
$b[1,0] = 30
$b[1,1] = 40
$c = $a + $b
$a.GetType().Name
$b.GetType().Name
$c.GetType().Name
$c

输出显示 是一维数组,其中包含行主序和 $c $a $b 行主序中的项。

Object[]
Int32[,]
Object[]
red
True
10
20
30
40

数组的方法

Clear

将所有元素值 设置为数组 的元素类型的默认值。 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(scriptblock expression, object[] arguments)
ForEach(type convertToType)
ForEach(string propertyName)
ForEach(string propertyName, object[] newValue)
ForEach(string methodName)
ForEach(string methodName, object[] arguments)

ForEach (scriptblock 表达式)

ForEach (scriptblock expression, object[] arguments)

此方法已添加到 PowerShell v4 中。

备注

语法需要使用脚本块。 如果 scriptblock 是唯一的参数,则括号是可选的。 此外,方法与左括号或大括号之间不得有空格。

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

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

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

有关 ArgumentList 的行为详细信息, 请参阅about_Splatting。

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[] 参数)

LastForEachly, 方法可用于对集合中每个项执行方法。

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

与 的参数一样, 参数允许将值数组传递给配置为接受这些值的 -ArgumentList ForEach-Object Arguments 脚本块。

备注

从 Windows PowerShell 3.0 开始,还可使用"标量对象和集合的方法"来检索集合中每个项的属性和执行方法。 可在此处阅读有关该about_methods。

其中

允许筛选或选择数组的元素。 脚本的计算结果必须不同于:0 (0) 空字符串,或元素在 之后 $false $null 显示 Where 。 有关布尔计算详细信息 ,请参阅about_Booleans。

方法有一个 Where 定义。

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

备注

语法需要使用脚本块。 如果 scriptblock 是唯一的参数,则括号是可选的。 此外,方法与左括号或大括号之间不得有空格。

是筛选所需的 scriptblock,可选参数允许其他选择功能,可选参数允许限制从筛选器返回 Expression mode numberToReturn 的项数。

可接受的值为 mode

  • Default (0) - 返回所有项
  • First (1) - 返回第一项
  • Last (2) - 返回最后一项
  • SkipUntil (3) - 跳过项直到条件为 true,则 返回剩余的项
  • Until (4) - 返回所有项,直到条件为 true
  • Split (5) - 返回两个元素的数组
    • 第一个元素包含匹配的项
    • 第二个元素包含剩余的项

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

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

此示例显示如何选择不为空的字符串。

('hi', '', 'there').Where({$_.Length})
hi
there

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 项,并可以互换使用。

Last

$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

Until模式反转 SkipUntil 模式。 它返回 集合 中的 ALL 项,直到项通过脚本块表达式。 一旦 项传递 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返回第一次 传递之前的项目

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

Split

模式 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
...

备注

foreach where 方法都是内部成员。 有关内部成员的信息 ,请参阅about_Instrinsic_Members

获取数组的成员

若要获取数组的属性和方法(如 属性和 Length SetValue 方法),请使用 cmdlet 的 InputObject Get-Member 参数。

通过管道将数组发送到 时,PowerShell 一次发送一个项,并返回数组中每个项的类型, (Get-Member Get-Member 忽略) 。

使用 InputObject 参数 时, Get-Member 返回数组的成员。

例如,以下命令获取数组变量 $a 的成员。

Get-Member -InputObject $a

还可以在通过管道将值通过管道 (,) 字符串,获取 Get-Member 数组的成员。 逗号使数组成为数组数组中的第二项。 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 实际上会使用原始数组的值和添加的值 += 创建一个新数组。 如果多次重复操作或数组大小太大,则可能会导致性能问题。

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

$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

也可使用 cmdlet,但分配 的值速度更快, Remove-Item $null 尤其是对于大型数组。

零或一的数组

从 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

对系统的索引编制支持。Tuple 对象

PowerShell 6.1 添加了对对象的索引访问 Tuple 的支持,类似于数组。 例如:

PS> $tuple = [Tuple]::Create(1, 'test')
PS> $tuple[0]
1
PS> $tuple[1]
test
PS> $tuple[0..1]
1
test
PS> $tuple[-1]
test

与数组和其他集合对象不同,通过管道或支持对象数组的参数传递对象时,对象将被视为 Tuple 单个对象。

有关详细信息,请参阅System. Tuple

另请参阅