Поделиться через


about_Arrays

Краткое описание

Описывает массивы, которые представляют собой структуры данных, предназначенные для хранения коллекций элементов.

Подробное описание

Массив — это структура данных, предназначенная для хранения коллекции элементов. Элементы могут иметь один и тот же тип или разные типы.

Начиная с Windows PowerShell 3.0 коллекция из нуля или одного объекта имеет некоторые свойства массивов.

Создание и инициализация массива

Чтобы создать и инициализировать массив, назначьте переменной несколько значений. Значения, хранящиеся в массиве, разделяются запятой и отделяются от имени переменной оператором присваивания (=).

Например, чтобы создать массив с именем $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.GetType()

Чтобы создать строго типизированный массив, то есть массив, который может содержать только значения определенного типа, приведите переменную к типу массива, например string[], long[] или int32[]. Чтобы привести массив, предваряйте имя переменной типом массива, заключенным в квадратные скобки. Пример:

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

В результате $ia массив может содержать только целые числа.

Можно создать массивы, которые приведены к любому поддерживаемому типу в .NET. Например, объекты, извлекаемые Get-Process для представления процессов, относятся к типу System.Diagnostics.Process . Чтобы создать строго типизированный массив объектов процесса, введите следующую команду:

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

Оператор вложенного выражения массива

Оператор вложенного выражения массива создает массив из инструкций внутри него. Независимо от того, что создает оператор внутри оператора, оператор помещает его в массив. Даже если объект равен нулю или одному.

Синтаксис оператора массива выглядит следующим образом:

@( ... )

Оператор массива можно использовать для создания массива с нулевым или одним объектом. Пример:

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

Оператор массива удобен в скриптах, когда вы получаете объекты, но не знаете, сколько следует ожидать. Пример:

$p = @(Get-Process Notepad)

Дополнительные сведения об операторе вложенного выражения массива см. в разделе about_Operators.

Доступ к элементам массива и их использование

Чтение массива

Вы можете ссылаться на массив, используя его имя переменной. Чтобы отобразить все элементы в массиве, вызовите имя массива. Например, $a является массивом чисел от 0 до 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

Кроме того, для перечисления нескольких диапазонов и отдельных элементов можно использовать оператор "плюс". Например, чтобы вывести список элементов с нуля до двух, от четырех до шести и элемента в восьмом позициональном типе:

$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 цикл для отображения элементов в массиве до тех пор, пока определенное условие не будет выполняться. Например, чтобы отобразить элементы в массиве $a , если индекс массива меньше 4, введите:

$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

Rank

Возвращает число измерений в массиве. Большинство массивов в PowerShell имеют только одно измерение. Даже если вы думаете, что вы создаете многомерный массив, как показано в следующем примере:

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

"`$a rank: $($a.Rank)"
"`$a length: $($a.Length)"
"`$a[2] length: $($a[2].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 представляет собой 1-мерный массив, содержащий элементы из $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, аргументы object[] )

Этот метод был добавлен в PowerShell версии 4.

Примечание

Синтаксис требует использования блока скрипта. Круглые скобки являются необязательными, если 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(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[] arguments)

LastТаким образом, ForEach() методы можно использовать для выполнения метода для каждого элемента в коллекции.

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

Как и параметр ArgumentList , параметр позволяет передавать массив значений в блок скрипта ForEach-Object, arguments настроенный для их принятия.

Примечание

Начиная с Windows PowerShell 3.0 получение свойств и выполнение методов для каждого элемента в коллекции также можно выполнять с помощью метода скалярных объектов и коллекций. Дополнительные сведения об этом см. здесь about_Methods.

Where()

Позволяет фильтровать или выбирать элементы массива. Скрипт должен иметь значение, отличное от нуля (0), пустой строки или $null элемента, $false отображаемого Where()после . Дополнительные сведения о логической оценке см. в разделе about_Booleans.

Существует одно определение метода Where() .

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

Примечание

Синтаксис требует использования блока скрипта. Круглые скобки являются необязательными, если scriptblock является единственным параметром. Кроме того, между методом и открывающей скобкой или фигурной скобкой не должно быть пробела.

Expression это scriptblock, необходимый для фильтрации, mode необязательный аргумент предоставляет дополнительные возможности выбора, а numberToReturn необязательный аргумент позволяет ограничить количество элементов, возвращаемых из фильтра.

Значение должно быть значением перечисления modeWhereOperatorSelectionMode :

  • 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 режим . Он возвращает ВСЕ элементы в коллекции, пока элемент не передаст выражение блока скрипта. Когда элемент передает выражение 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 возвращает элементы ДО первого PASS. 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 , используйте параметр InputObject командлета Get-Member .

При конвейере массива Get-Memberв PowerShell отправляет элементы по одному и Get-Member возвращает тип каждого элемента в массиве (игнорируя дубликаты).

При использовании параметра Get-MemberInputObject возвращает элементы массива.

Например, следующая команда получает элементы переменной массива $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 фактически создает новый массив со значениями исходного массива и добавленного значения. Это может привести к проблемам с производительностью, если операция повторяется несколько раз или размер массива слишком велик.

Удалить элементы из массива непросто, но можно создать новый массив, содержащий только выбранные элементы существующего массива. Например, чтобы создать $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 командлет , но назначение значения $null выполняется быстрее, особенно для больших массивов.

Массивы, равные нулю или единице

Начиная с Windows PowerShell 3.0 коллекция из нуля или одного объекта имеет Count свойства и Length . Кроме того, можно индексировать в массиве одного объекта. Эта функция помогает избежать ошибок скриптов, возникающих, когда команда, ожидающая коллекцию, получает менее двух элементов.

В следующем примере показано, что переменная, которая не содержит объектов, имеет Count значение и Length 0.

PS> $a = $null
PS> $a.Count
0
PS> $a.Length
0

В следующем примере показано, что переменная, содержащая один объект, имеет Count значение и Length 1. Для доступа к значению объекта можно также использовать индексирование массивов.

PS> $a = 4
PS> $a.Count
1
PS> $a.Length
1
PS> $a[0]
4
PS> $a[-1]
4

При выполнении команды, которая может вернуть коллекцию или один объект, можно использовать индексирование массива для доступа к значению объекта без необходимости проверки Count свойств или Length . Однако если результатом является одиночный объект (singleton) и этот объект имеет Count свойство или Length , значение этих свойств принадлежит объекту singleton и не представляет количество элементов в коллекции.

В следующем примере команда возвращает один строковый объект. Для Length этой строки задано значение 4.

PS> $result = 'one','two','three','four' | Where-Object {$_ -like 'f*'}
PS> $result.GetType().FullName
System.String
PS> $result
four
PS> $result.Count
1
PS❯ $result.Length
4

Если вы хотите $result быть массивом строк, необходимо объявить переменную как массив.

В этом примере $result представляет собой массив строк. И Count массива — 1, а Length для первого элемента — 4.Length

PS> [string[]]$result = 'one','two','three','four' |
    Where-Object {$_ -like 'f*'}
PS> $result.GetType().FullName
System.String[]
PS> $result
four
PS> $result.Count
1
PS> $result.Length
1
PS> $result[0].Length
4

Поддержка индексирования для System.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.

Индексирование типов .NET, реализующих IDictionary<TKey, TValue>

PowerShell не вызывает истинный индексатор типа для типов, реализующих универсальный IDictionary<TKey, TValue> интерфейс. Вместо этого, если задан ключ, PowerShell проверяет наличие ключа с помощью TryGetValue(), который возвращает $null , если ключ не существует.

В отличие от этого, если вызвать истинный индексатор типа с помощью Item(<key>), метод создает исключение, если ключ не существует.

В следующем примере демонстрируется это различие.

PS> [Collections.Generic.Dictionary[string, int]]::new()['nosuchkey']
# No output ($null)

PS> [Collections.Generic.Dictionary[string, int]]::new().Item('nosuchkey')
GetValueInvocationException: Exception getting "Item": "The given key 'nosuchkey'
 was not present in the dictionary."

Перечисление доступа к членам

Начиная с PowerShell 3.0, при использовании оператора доступа к членам для доступа к элементу, который не существует в коллекции списков, PowerShell автоматически перечисляет элементы в коллекции и пытается получить доступ к указанному члену для каждого элемента. Дополнительные сведения см. в разделе about_Member-Access_Enumeration.

Примеры

В следующем примере создаются два новых файла и сохраняются результирующие объекты в переменной $filesмассива . Так как объект массива не имеет Lastэлемента WriteTime , для каждого элемента в массиве возвращается значение LastWriteTime .

$files = (New-Item -Type File -Force '/temp/t1.txt'),
         (New-Item -Force -Type File '/temp/t2.txt')
$files.LastWriteTime
Friday, June 25, 2021 1:21:17 PM
Friday, June 25, 2021 1:21:17 PM

Перечисление доступа к членам позволяет получать значения из элементов в коллекции, но не задавать значения для элементов в коллекции. Пример:

$files.LastWriteTime = (Get-Date).AddDays(-1)
InvalidOperation: The property 'LastWriteTime' cannot be found on this object.
Verify that the property exists and can be set.

Чтобы задать значения, необходимо использовать метод .

$files.set_LastWriteTime((Get-Date).AddDays(-1))
$files.LastWriteTime
Thursday, June 24, 2021 1:23:30 PM
Thursday, June 24, 2021 1:23:30 PM

Метод set_LastWriteTime() является скрытым элементом объекта FileInfo . В следующем примере показано, как найти элементы со скрытымset методом.

$files | Get-Member | Where-Object Definition -like '*set;*'
   TypeName: System.IO.FileInfo

Name              MemberType Definition
----              ---------- ----------
Attributes        Property   System.IO.FileAttributes Attributes {get;set;}
CreationTime      Property   datetime CreationTime {get;set;}
CreationTimeUtc   Property   datetime CreationTimeUtc {get;set;}
IsReadOnly        Property   bool IsReadOnly {get;set;}
LastAccessTime    Property   datetime LastAccessTime {get;set;}
LastAccessTimeUtc Property   datetime LastAccessTimeUtc {get;set;}
LastWriteTime     Property   datetime LastWriteTime {get;set;}
LastWriteTimeUtc  Property   datetime LastWriteTimeUtc {get;set;}

Внимание!

Так как метод выполняется для каждого элемента в коллекции, при вызове методов с помощью перечисления элементов следует соблюдать осторожность.

См. также раздел