배열은 대부분의 프로그래밍 언어의 기본 언어 기능입니다. 이 컬렉션은 피하기 어려운 값 또는 개체의 컬렉션입니다. 배열과 그것이 제공하는 모든 것을 자세히 살펴보겠습니다.
비고
이 문서의 원래 버전@KevinMarquette작성한 블로그에 나타났습니다. PowerShell 팀은 이 콘텐츠를 공유해 주신 Kevin에게 감사드립니다. PowerShellExplained.com자신의 블로그를 확인하세요.
배열이란?
PowerShell에서 사용하는 다른 방법으로 전환하기 전에 배열이 무엇이고 대부분의 프로그래밍 언어에서 어떻게 사용되는지에 대한 기본 기술 설명부터 시작하겠습니다.
배열은 여러 항목의 컬렉션 역할을 하는 데이터 구조입니다. 배열을 반복하거나 인덱스로 개별 항목에 액세스할 수 있습니다. 배열은 각 값이 다른 값 바로 옆에 저장되는 순차적 메모리 청크로 만들어집니다.
우리는 진행하면서 각각의 세부 사항을 다루겠습니다.
기본 사용법
배열은 PowerShell의 기본 기능이므로 PowerShell에서 작업하기 위한 간단한 구문이 있습니다.
배열 만들기
빈 배열을 사용하여 만들 수 있습니다. @()
PS> $data = @()
PS> $data.Count
0
배열을 만들고 괄호 안에 값을 배치하여 초기화할 수 있습니다.
PS> $data = @('Zero','One','Two','Three')
PS> $data.Count
4
PS> $data
Zero
One
Two
Three
이 배열에는 4개 항목이 있습니다. 변수를 $data
호출하면 항목 목록이 표시됩니다. 문자열 배열인 경우 문자열당 한 줄을 가져옵니다.
여러 줄에 배열을 선언할 수 있습니다. 이 경우 쉼표는 선택 사항이며 일반적으로 제외됩니다.
$data = @(
'Zero'
'One'
'Two'
'Three'
)
나는 그런 여러 줄에 내 배열을 선언하는 것을 선호합니다. 항목이 여러 대 있을 때 더 쉽게 읽을 수 있을 뿐만 아니라 소스 제어를 사용할 때 이전 버전과 더 쉽게 비교할 수 있습니다.
기타 구문
컴퓨터 언어에서 @()
는 배열을 생성하는 구문으로 일반적으로 이해되지만, 쉼표로 구분된 목록이 대부분의 경우 작동합니다.
$data = 'Zero','One','Two','Three'
Write-Output 배열을 만들기 위해
언급할 만한 멋진 작은 트릭 중 하나는 콘솔에서 문자열을 빠르게 만드는 데 사용할 Write-Output
수 있다는 것입니다.
$data = Write-Output Zero One Two Three
매개 변수가 문자열을 수락할 때 문자열 주위에 따옴표를 넣을 필요가 없으므로 편리합니다. 나는 스크립트에서 이 작업을 수행하지 않을 것이나, 콘솔에서는 허용된다.
항목 접근
이제 항목이 포함된 배열이 있으므로 해당 항목에 액세스하고 업데이트할 수 있습니다.
상쇄
개별 항목에 액세스하려면 오프셋 값이 []
0부터 시작하는 대괄호를 사용합니다. 배열의 첫 번째 항목을 가져오는 방법은 다음과 같습니다.
PS> $data = 'Zero','One','Two','Three'
PS> $data[0]
Zero
여기서 0을 사용하는 이유는 첫 번째 항목이 목록의 시작 부분에 있으므로 0개 항목의 오프셋을 사용하여 가져오기 때문입니다. 두 번째 항목으로 이동하려면 첫 번째 항목을 건너뛰려면 1의 오프셋을 사용해야 합니다.
PS> $data[1]
One
이는 마지막 항목이 오프셋 3에 있음을 의미합니다.
PS> $data[3]
Three
인덱스
이제 이 예제에서 내가 한 값을 선택한 이유를 확인할 수 있습니다. 이것이 실제로 무엇이기 때문에 이것을 오프셋으로 소개했지만, 이 오프셋은 더 일반적으로 인덱스라고 합니다. 에서 0
시작하는 인덱스입니다. 이 문서의 나머지 부분에 대해 오프셋을 인덱스라고 합니다.
특수 인덱스 트릭
대부분의 언어에서는 단일 숫자만 인덱스로 지정할 수 있으며 단일 항목을 다시 가져올 수 있습니다. PowerShell은 훨씬 더 유연합니다. 한 번에 여러 인덱스를 사용할 수 있습니다. 인덱스 목록을 제공하여 여러 항목을 선택할 수 있습니다.
PS> $data[0,2,3]
Zero
Two
Three
항목은 제공된 인덱스의 순서에 따라 반환됩니다. 인덱스가 중복되면 해당 항목을 두 번 모두 가져옵니다.
PS> $data[3,0,3]
Three
Zero
Three
기본 제공 연산자를 사용하여 숫자 시퀀스를 지정할 수 있습니다 ..
.
PS> $data[1..3]
One
Two
Three
이것은 역으로도 작동합니다.
PS> $data[3..1]
Three
Two
One
음수 인덱스 값을 사용하여 끝에서부터 조정할 수 있습니다. 따라서 목록에서 마지막 항목이 필요한 경우 사용할 -1
수 있습니다.
PS> $data[-1]
Three
..
연산자에 대해 주의해야 할 점이 있습니다. 시퀀스 0..-1
와 -1..0
는 각각 값 0,-1
와 -1,0
로 평가됩니다. 세부 사항을 잊으면 $data[0..-1]
가 모든 항목을 열거한다고 쉽게 생각할 수 있습니다.
$data[0..-1]
는 배열의 첫 번째 항목과 마지막 항목을 제공하는 것과 $data[0,-1]
동일한 값을 제공합니다(다른 값은 없음). 다음은 더 큰 예제입니다.
PS> $a = 1,2,3,4,5,6,7,8
PS> $a[2..-1]
3
2
1
8
이는 다음과 같습니다.
PS> $a[2,1,0,-1]
3
2
1
8
범위를 벗어났습니다.
대부분의 언어에서 배열의 끝을 지난 항목의 인덱스에 액세스하려고 하면 일부 유형의 오류 또는 예외가 발생합니다. PowerShell은 아무 것도 자동으로 반환하지 않습니다.
PS> $null -eq $data[9000]
True
null 배열로 인덱싱할 수 없음
변수가 $null
이고 이를 배열처럼 인덱싱하려고 하면, 메시지 Cannot index into a null array
와 함께 System.Management.Automation.RuntimeException
예외가 발생합니다.
PS> $empty = $null
PS> $empty[0]
Error: Cannot index into a null array.
배열 내부의 요소에 액세스하기 전에 배열이 비어있지 않은지 $null
확인하세요.
수량
배열 및 기타 컬렉션에는 배열에 Count
있는 항목 수를 알려주는 속성이 있습니다.
PS> $data.Count
4
PowerShell 3.0은 Count
대부분의 개체에 속성을 추가했습니다. 단일 개체를 가질 수 있으며 개수를 1
제공해야 합니다.
PS> $date = Get-Date
PS> $date.Count
1
$null
도 Count
속성이 있으며, 이 속성은 0
을 반환합니다.
PS> $null.Count
0
이 기사에서 나중에 $null
을(를) 확인하거나 빈 배열을 다룰 때 다시 설명할 몇 가지 함정이 있습니다.
1차 오류
배열이 인덱스 0에서 시작되므로 일반적인 프로그래밍 오류가 생성됩니다. 오프 바이 원 에러는 두 가지 방법으로 발생할 수 있습니다.
두 번째 항목을 마음속으로 원한다고 생각하면서 인덱스 2
를 사용하여 실제로 세 번째 항목을 가져오는 것입니다. 또는 4개의 항목이 있고 마지막 항목을 원한다고 생각하여 개수를 사용하여 마지막 항목에 액세스합니다.
$data[ $data.Count ]
PowerShell을 사용하면 인덱스 4 $null
에 있는 항목을 정확하게 제공할 수 있습니다. 당신은 $data.Count - 1
또는 위에서 배운 -1
를 사용해야 합니다.
PS> $data[ $data.Count - 1 ]
Three
인덱스 -1
로 마지막 요소를 가져올 수 있습니다.
PS> $data[ -1 ]
Three
Lee Dailey는 또한 우리가 $data.GetUpperBound(0)
를 사용해서 최대 인덱스 번호를 취할 수 있다고 지적했습니다.
PS> $data.GetUpperBound(0)
3
PS> $data[ $data.GetUpperBound(0) ]
Three
두 번째로 일반적인 방법은 목록을 반복하고 적절한 시간에 중지하지 않는 경우입니다.
for
루프 사용에 대해 이야기할 때 이것을 다시 살펴보겠습니다.
항목 업데이트
동일한 인덱스로 배열의 기존 항목을 업데이트할 수 있습니다. 이렇게 하면 개별 항목을 업데이트하는 데 직접 액세스할 수 있습니다.
$data[2] = 'dos'
$data[3] = 'tres'
마지막 요소를 지난 항목을 업데이트하려고 하면 오류가 발생합니다 Index was outside the bounds of the array.
.
PS> $data[4] = 'four'
Index was outside the bounds of the array.
At line:1 char:1
+ $data[4] = 'four'
+ ~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], IndexOutOfRangeException
+ FullyQualifiedErrorId : System.IndexOutOfRangeException
나중에 배열을 더 크게 만드는 방법에 대해 이야기할 때 이를 다시 살펴보겠습니다.
반복
어떤 시점에서 전체 목록을 걷거나 반복하고 배열의 각 항목에 대해 몇 가지 작업을 수행해야 할 수 있습니다.
파이프라인
배열과 PowerShell 파이프라인은 서로를 위한 것입니다. 이러한 값을 처리하는 가장 간단한 방법 중 하나입니다. 배열을 파이프라인에 전달하면 배열 내의 각 항목이 개별적으로 처리됩니다.
PS> $data = 'Zero','One','Two','Three'
PS> $data | ForEach-Object {"Item: [$PSItem]"}
Item: [Zero]
Item: [One]
Item: [Two]
Item: [Three]
이전에 $PSItem
을(를) 본 적이 없다면, 그것이 $_
과(와) 같은 것임을 알아두세요. 둘 다 파이프라인의 현재 개체를 나타내므로 둘 중 하나를 사용할 수 있습니다.
ForEach 루프
루프는 foreach
컬렉션에서 잘 작동합니다. 구문 사용: foreach ( <variable> in <collection> )
foreach ( $node in $data )
{
"Item: [$node]"
}
ForEach 메서드
나는이 것에 대해 잊어 버리는 경향이 있지만 간단한 작업에 잘 작동합니다. PowerShell을 사용하면 컬렉션을 호출 ForEach()
할 수 있습니다.
PS> $data.ForEach({"Item [$PSItem]"})
Item [Zero]
Item [One]
Item [Two]
Item [Three]
스크립트 ForEach()
블록인 매개 변수를 가져옵니다. 괄호를 삭제하고 스크립트 블록을 제공할 수 있습니다.
$data.ForEach{"Item [$PSItem]"}
덜 알려진 구문이지만 동일하게 작동합니다. 이 ForEach
메서드는 PowerShell 4.0에 추가되었습니다.
For 루프
루프 for
는 대부분의 다른 언어에서 많이 사용되지만 PowerShell에서는 많이 표시되지 않습니다. 당신이 그것을 볼 때, 그것은 종종 배열을 순회하는 맥락에서 나타납니다.
for ( $index = 0; $index -lt $data.Count; $index++)
{
"Item: [{0}]" -f $data[$index]
}
가장 먼저 할 일은 $index
을 0
로 초기화하는 것입니다. 그런 다음 , 보다 $data.Count
작아야 하는 $index
조건을 추가합니다. 마지막으로, 루프할 때마다 인덱스를 1
만큼 증가시켜야 한다고 명시합니다. 이 경우 $index++
는 $index = $index + 1
의 줄임말입니다.
형식 연산자(-f
)는 출력 문자열의 $data[$index]
값을 삽입하는 데 사용됩니다.
for
루프를 사용할 때마다 조건에 특별히 주의하세요. 나는 여기에 사용했다 $index -lt $data.Count
. 논리에서 조건을 약간 잘못 설정하여 오프 바이 원 오류를 발생시키는 것은 쉽습니다.
$index -le $data.Count
또는 $index -lt ($data.Count - 1)
의 사용은 조금 틀립니다. 이로 인해 결과가 너무 많거나 너무 적은 항목을 처리하게 됩니다. 이것은 클래식 오프 바이 원 오류입니다.
스위치 루프
이것은 간과하기 쉬운 것입니다. switch 문에 배열을 제공하는 경우 배열의 각 항목을 확인합니다.
$data = 'Zero','One','Two','Three'
switch( $data )
{
'One'
{
'Tock'
}
'Three'
{
'Tock'
}
Default
{
'Tick'
}
}
Tick
Tock
Tick
Tock
switch 문으로 할 수 있는 멋진 일들이 많이 있습니다. 나는 이것에 전념하는 또 다른 기사가 있다.
값 업데이트
배열이 문자열 또는 정수(값 형식)의 컬렉션인 경우 배열을 반복할 때 배열의 값을 업데이트할 수 있습니다. 위의 대부분의 루프는 값의 복사본을 보유하는 루프의 변수를 사용합니다. 해당 변수를 업데이트하면 배열의 원래 값이 업데이트되지 않습니다.
해당 문의 예외는 루프입니다 for
. 배열을 순회하고 그 안의 값을 업데이트하려는 경우 for
루프가 필요합니다.
for ( $index = 0; $index -lt $data.Count; $index++ )
{
$data[$index] = "Item: [{0}]" -f $data[$index]
}
이 예제에서는 인덱스별로 값을 가져와서 몇 가지 변경한 다음 동일한 인덱스로 다시 할당합니다.
개체 배열
지금까지 배열에 배치한 유일한 항목은 값 형식이지만 배열에는 개체도 포함될 수 있습니다.
$data = @(
[pscustomobject]@{FirstName='Kevin';LastName='Marquette'}
[pscustomobject]@{FirstName='John'; LastName='Doe'}
)
많은 cmdlet은 개체 컬렉션을 변수에 할당할 때 배열로 반환합니다.
$processList = Get-Process
이미 설명한 모든 기본 기능은 몇 가지 세부 정보가 있는 개체 배열에 여전히 적용됩니다.
액세스 속성
인덱스로 값 형식과 마찬가지로 컬렉션의 개별 항목에 액세스할 수 있습니다.
PS> $data[0]
FirstName LastName
----- ----
Kevin Marquette
속성에 직접 액세스하고 업데이트할 수 있습니다.
PS> $data[0].FirstName
Kevin
PS> $data[0].FirstName = 'Jay'
PS> $data[0]
FirstName LastName
----- ----
Jay Marquette
배열 속성
일반적으로 모든 속성에 액세스하려면 다음과 같이 전체 목록을 열거해야 합니다.
PS> $data | ForEach-Object {$_.LastName}
Marquette
Doe
Select-Object -ExpandProperty
cmdlet을 사용하거나.
PS> $data | Select-Object -ExpandProperty LastName
Marquette
Doe
그러나 PowerShell은 직접 요청할 LastName
수 있는 기능을 제공합니다. PowerShell은 모두 열거하고 정리 목록을 반환합니다.
PS> $data.LastName
Marquette
Doe
열거형은 여전히 발생하지만 그 뒤에 복잡성은 보이지 않습니다.
Where-Object 필터링
개체의 속성에 따라 배열에서 원하는 내용을 필터링하고 선택할 수 있도록 이 위치 Where-Object
가 제공됩니다.
PS> $data | Where-Object {$_.FirstName -eq 'Kevin'}
FirstName LastName
----- ----
Kevin Marquette
동일한 쿼리를 작성하여 찾고 있는 FirstName
를 가져올 수 있습니다.
$data | where FirstName -EQ Kevin
Where()
배열에는 특정 필터 기준을 지정할 수 있는 Where()
메서드가 scriptblock
있습니다.
$data.Where({$_.FirstName -eq 'Kevin'})
이 기능은 PowerShell 4.0에 추가되었습니다.
루프에서 개체 업데이트
값 형식을 사용하면 값을 바꿀 인덱스만 알아야 하므로 배열을 업데이트하는 유일한 방법은 for 루프를 사용하는 것입니다. 개체는 참조 형식이므로 더 많은 옵션이 있습니다. 다음은 빠른 예제입니다.
foreach($person in $data)
{
$person.FirstName = 'Kevin'
}
이 루프는 배열의 모든 개체를 걷고 있습니다 $data
. 개체는 참조 형식이므로 변수는 $person
배열에 있는 것과 정확히 동일한 개체를 참조합니다. 따라서 해당 속성에 대한 업데이트는 원본을 업데이트합니다.
여전히 전체 개체를 이런 식으로 바꿀 수는 없습니다. 변수에 새 개체를 $person
할당하려고 하면 변수 참조를 배열의 원래 개체를 더 이상 가리키지 않는 다른 개체로 업데이트합니다. 이 작업은 예상한 것처럼 작동하지 않습니다.
foreach($person in $data)
{
$person = [pscustomobject]@{
FirstName='Kevin'
LastName='Marquette'
}
}
운영자
PowerShell의 연산자도 배열에서 작동합니다. 그들 중 일부는 약간 다르게 작동합니다.
-가입
-join
연산자가 가장 확실한 연산자이므로 먼저 살펴보겠습니다. 나는 연산자를 -join
좋아하고 자주 사용합니다. 배열의 모든 요소를 지정한 문자 또는 문자열과 조인합니다.
PS> $data = @(1,2,3,4)
PS> $data -join '-'
1-2-3-4
PS> $data -join ','
1,2,3,4
연산자에 대해 -join
좋아하는 기능 중 하나는 단일 항목을 처리한다는 것입니다.
PS> 1 -join '-'
1
저는 로깅 및 자세한 메시지 내에서 이것을 사용합니다.
PS> $data = @(1,2,3,4)
PS> "Data is $($data -join ',')."
Data is 1,2,3,4.
-join $배열
리 데일리가 내게 지적한 영리한 트릭은 다음과 같습니다. 구분 기호 없이 모든 항목을 조인하려는 경우 다음을 수행하는 대신 다음을 수행합니다.
PS> $data = @(1,2,3,4)
PS> $data -join $null
1234
접두사 없이 배열을 매개 변수로 사용할 -join
수 있습니다. 이 예제를 살펴 보면 내가 말하는 것을 볼 수 있습니다.
PS> $data = @(1,2,3,4)
PS> -join $data
1234
-replace 및 -split
다른 연산자는 -replace
와 -split
처럼 배열의 각 항목에 대해 실행됩니다. 나는 이런 식으로 그들을 사용한 적이 있다고 말할 수는 없지만 여기에 예가 있습니다.
PS> $data = @('ATX-SQL-01','ATX-SQL-02','ATX-SQL-03')
PS> $data -replace 'ATX','LAX'
LAX-SQL-01
LAX-SQL-02
LAX-SQL-03
포함하다
-contains
연산자를 사용하면 값 배열을 확인하여 지정된 값이 포함되어 있는지 확인할 수 있습니다.
PS> $data = @('red','green','blue')
PS> $data -contains 'green'
True
-in
여러 값 중 하나와 일치하는지 확인하려는 단일 값이 있는 경우 연산자를 -in
사용할 수 있습니다. 값은 왼쪽에 있고 배열은 연산자의 오른쪽에 있습니다.
PS> $data = @('red','green','blue')
PS> 'green' -in $data
True
목록이 크면 비용이 많이 들 수 있습니다. 몇 개 이상의 값을 확인하는 경우 종종 정규식 패턴을 사용합니다.
PS> $data = @('red','green','blue')
PS> $pattern = "^({0})$" -f ($data -join '|')
PS> $pattern
^(red|green|blue)$
PS> 'green' -match $pattern
True
-eq 및 -ne
동등성과 배열은 복잡해질 수 있습니다. 배열이 왼쪽에 있으면 모든 항목이 비교됩니다. 반환하는 True
대신 일치하는 개체를 반환합니다.
PS> $data = @('red','green','blue')
PS> $data -eq 'green'
green
연산자를 -ne
사용하면 값과 같지 않은 모든 값이 표시됩니다.
PS> $data = @('red','green','blue')
PS> $data -ne 'green'
red
blue
문장에서 if()
을 사용하면 반환되는 값은 True
값입니다. 값이 반환되지 않으면 이는 False
값입니다. 다음 두 문장은 모두 True
로 평가됩니다.
$data = @('red','green','blue')
if ( $data -eq 'green' )
{
'Green was found'
}
if ( $data -ne 'green' )
{
'And green was not found'
}
잠시 후, $null
에 대한 테스트를 이야기할 때 다시 살펴보겠습니다.
-매치
연산자는 -match
컬렉션의 각 항목과 일치하려고 시도합니다.
PS> $servers = @(
'LAX-SQL-01'
'LAX-API-01'
'ATX-SQL-01'
'ATX-API-01'
)
PS> $servers -match 'SQL'
LAX-SQL-01
ATX-SQL-01
단일 값으로 사용하면 -match
특수 변수 $Matches
가 일치 정보로 채워집니다. 배열이 이런 방식으로 처리되는 경우는 그렇지 않습니다.
동일한 접근 방식을 Select-String
을 사용하여 취할 수 있습니다.
$servers | Select-String SQL
나는 다른 게시물인 regex를 사용하는 여러 가지 방법에서 Select-String
, -match
및 $Matches
변수를 자세히 살펴봅니다.
$null 또는 비어 있음
$null
또는 빈 배열을 테스트하는 것은 까다로울 수 있습니다. 배열이 있는 일반적인 트랩은 다음과 같습니다.
이 문장은 얼핏 보면 작동할 것처럼 보입니다.
if ( $array -eq $null)
{
'Array is $null'
}
방금 전에 배열의 각 항목을 확인하는 방법을 -eq
알아봤습니다. 따라서 단일 $null 값을 가진 여러 항목의 배열을 가질 수 있으며, 이는 $true
로 평가됩니다.
$array = @('one',$null,'three')
if ( $array -eq $null)
{
'I think Array is $null, but I would be wrong'
}
이 때문에 연산자의 왼쪽에 배치 $null
하는 것이 가장 좋습니다. 따라서 이 시나리오는 문제가 되지 않습니다.
if ( $null -eq $array )
{
'Array actually is $null'
}
배열은 $null
빈 배열과 동일하지 않습니다. 배열이 있다는 것을 알고 있는 경우 배열의 개체 수를 확인합니다. 배열이 $null
면 개수는 .입니다 0
.
if ( $array.Count -gt 0 )
{
"Array isn't empty"
}
여기에 주의해야 할 함정이 하나 더 있습니다.
Count
는 단일 개체가 있는 경우에도 사용할 수 있으며, 그 개체가 PSCustomObject
이 아닌 경우에만 가능합니다. PowerShell 6.1에서 수정된 버그입니다.
좋은 소식이지만 많은 사람들이 여전히 5.1에 있으며 조심해야합니다.
PS> $object = [pscustomobject]@{Name='TestObject'}
PS> $object.Count
$null
PowerShell 5.1을 계속 사용하는 경우 개수를 확인하기 전에 배열에서 개체를 래핑하여 정확한 개수를 가져올 수 있습니다.
if ( @($array).Count -gt 0 )
{
"Array isn't empty"
}
안전을 완전히 확보하려면 먼저 $null
를 확인한 다음, 개수를 확인하십시오.
if ( $null -ne $array -and @($array).Count -gt 0 )
{
"Array isn't empty"
}
모든 -eq
최근에 Reddit의 누군가가 배열의 모든 값이 지정된 값과 일치하는지 확인하는 방법을 묻는 것을 보았습니다. Reddit 사용자는 u/bis
잘못된 값을 확인한 다음 결과를 뒤집는 이 영리한 솔루션을 사용했습니다.
$results = Test-Something
if ( -not ( $results -ne 'Passed') )
{
'All results a Passed'
}
배열에 추가
이 시점에서 배열에 항목을 추가하는 방법을 궁금해하기 시작했습니다. 빠른 대답은 당신이 할 수 없다는 것입니다. 배열은 메모리의 고정 크기입니다. 확장하거나 단일 항목을 추가해야 하는 경우 새 배열을 만들고 이전 배열에서 모든 값을 복사해야 합니다. 이는 많은 작업처럼 들리지만 PowerShell은 새 배열을 만드는 복잡성을 숨깁니다. PowerShell은 배열에 대한 더하기 연산자(+
)를 구현합니다.
비고
PowerShell은 빼기 작업을 구현하지 않습니다. 배열을 유연하게 대체하려면 제네릭 List
개체를 사용해야 합니다.
배열 추가
배열과 함께 더하기 연산자를 사용하여 새 배열을 만들 수 있습니다. 따라서 다음 두 배열을 지정합니다.
$first = @(
'Zero'
'One'
)
$second = @(
'Two'
'Three'
)
함께 추가하여 새 배열을 가져올 수 있습니다.
PS> $first + $second
Zero
One
Two
Three
Plus equals +=
새 배열을 만들고 다음과 같이 항목을 추가할 수 있습니다.
$data = @(
'Zero'
'One'
'Two'
'Three'
)
$data += 'four'
매번 +=
를 사용할 때마다 새로운 배열을 복사하고 생성한다는 것을 기억하세요. 이는 작은 데이터 세트에서는 문제가 되지 않지만, 매우 비효율적으로 확장됩니다.
파이프라인 할당
파이프라인의 결과를 변수에 할당할 수 있습니다. 여러 항목이 포함된 경우 배열입니다.
$array = 1..5 | ForEach-Object {
"ATX-SQL-$PSItem"
}
일반적으로 파이프라인을 사용할 때 보통 PowerShell 명령문을 떠올립니다. 명령문과 기타 루프를 foreach()
를 사용하여 파이프라인을 활용할 수 있습니다. 따라서 루프의 배열에 항목을 추가하는 대신 파이프라인에 항목을 삭제할 수 있습니다.
$array = foreach ( $node in (1..5))
{
"ATX-SQL-$node"
}
배열 형식
기본적으로 PowerShell의 배열은 형식으로 [psobject[]]
만들어집니다. 이렇게 하면 모든 형식의 개체 또는 값을 포함할 수 있습니다. 이는 모든 것이 PSObject
유형으로부터 상속되기 때문에 작동합니다.
강력한 형식의 배열
비슷한 구문을 사용하여 모든 형식의 배열을 만들 수 있습니다. 강력한 형식의 배열을 만들 때 지정된 형식의 값이나 개체만 포함할 수 있습니다.
PS> [int[]] $numbers = 1,2,3
PS> [int[]] $numbers2 = 'one','two','three'
ERROR: Cannot convert value "one" to type "System.Int32". Input string was not in a correct format."
PS> [string[]] $strings = 'one','two','three'
ArrayList(배열 리스트)
배열에 항목을 추가하는 것은 가장 큰 제한 사항 중 하나이지만 이 문제를 해결할 수 있는 몇 가지 다른 컬렉션이 있습니다.
ArrayList
일반적으로 작업 속도가 더 빠른 배열이 필요할 때 가장 먼저 생각하는 항목 중 하나입니다. 필요한 모든 위치에서 개체 배열처럼 작동하지만 항목 추가를 신속하게 처리합니다.
항목을 만들고 ArrayList
추가하는 방법은 다음과 같습니다.
$myarray = [System.Collections.ArrayList]::new()
[void]$myArray.Add('Value')
이 형식을 가져오기 위해 .NET을 호출합니다. 이 경우 기본 생성자를 사용하여 만듭니다. 그런 다음, 메서드를 Add
호출하여 항목을 추가합니다.
줄 시작 부분에서 [void]
를 사용하는 이유는 반환 코드를 억제하기 위해서입니다. 일부 .NET 호출은 이 작업을 수행하며 예기치 않은 출력을 만들 수 있습니다.
배열에 있는 유일한 데이터가 문자열인 경우 StringBuilder 사용도 살펴봅니다. 거의 동일하지만 문자열을 처리하기 위한 몇 가지 메서드가 있습니다. 이 StringBuilder
디자인은 성능을 위해 특별히 설계되었습니다.
배열에서 ArrayList
로 전환하는 것을 보는 것이 일반적입니다. 그러나 C#이 일반적인 지원을 받지 못했던 때에서 비롯되었습니다.
ArrayList
는 일반적인 List[]
를 지원하기 위해 더 이상 사용되지 않습니다.
제네릭 목록
제네릭 형식은 일반화된 클래스를 정의하는 C#의 특수 형식이며 사용자가 만들 때 사용하는 데이터 형식을 지정합니다. 따라서 숫자 또는 문자열 목록을 원하는 경우 목록 int
또는 string
형식을 정의합니다.
문자열 목록을 만드는 방법은 다음과 같습니다.
$mylist = [System.Collections.Generic.List[string]]::new()
또는 숫자 목록입니다.
$mylist = [System.Collections.Generic.List[int]]::new()
먼저 개체를 만들지 않고 기존 배열을 다음과 같은 목록으로 캐스팅할 수 있습니다.
$mylist = [System.Collections.Generic.List[int]]@(1,2,3)
PowerShell 5 이상 버전에서는 using namespace
문을 사용하여 코드 구문을 줄일 수 있습니다.
using
구문은 스크립트의 첫 번째 줄에 반드시 있어야 합니다. 네임스페이스를 선언하면 PowerShell을 사용하면 해당 네임스페이스를 참조할 때 데이터 형식에서 제외할 수 있습니다.
using namespace System.Collections.Generic
$myList = [List[int]]@(1,2,3)
이렇게 하면 List
훨씬 더 쉽게 사용할 수 있습니다.
비슷한 Add
방법을 사용할 수 있습니다. ArrayList와 달리 Add
메서드에는 반환 값이 없으므로 void
할 필요가 없습니다.
$myList.Add(10)
또한 다른 배열과 같은 요소에 계속 액세스할 수 있습니다.
PS> $myList[-1]
10
List[psobject]
모든 형식의 목록을 가질 수 있지만 개체의 형식을 모르는 경우 개체를 포함하는 데 사용할 [List[psobject]]
수 있습니다.
$list = [List[psobject]]::new()
제거()
ArrayList
제네릭 List[]
은 모두 컬렉션에서 항목 제거를 지원합니다.
using namespace System.Collections.Generic
$myList = [List[string]]@('Zero','One','Two','Three')
[void]$myList.Remove("Two")
Zero
One
Three
값 형식을 사용할 때 목록에서 첫 번째 값을 제거합니다. 이 값을 계속 제거하려면 반복해서 호출할 수 있습니다. 참조 형식이 있는 경우 제거할 개체를 제공해야 합니다.
[List[System.Management.Automation.PSDriveInfo]]$drives = Get-PSDrive
$drives.Remove($drives[2])
$delete = $drives[2]
$drives.Remove($delete)
remove 메서드는 컬렉션에서 항목을 찾아 제거할 수 있으면 반환 true
합니다.
추가 컬렉션
사용할 수 있는 다른 많은 컬렉션이 있지만, 이것들은 좋은 제네릭 배열 대안입니다. 이러한 옵션에 대해 자세히 알아보려면 Mark Kraus가 함께 사용한 이 시스트를 살펴보세요.
기타 뉘앙스
이제 모든 주요 기능을 다루었으므로 이것을 마무리하기 전에 언급하고 싶었던 몇 가지 사항이 있습니다.
미리 크기가 조정된 배열
배열을 만든 후에는 배열의 크기를 변경할 수 없다고 언급했습니다. 생성자를 사용하여 호출하여 미리 결정된 크기의 배열을 new($size)
만들 수 있습니다.
$data = [Object[]]::new(4)
$data.Count
4
배열 곱하기
흥미로운 작은 비결은 배열을 정수로 곱할 수 있다는 것입니다.
PS> $data = @('red','green','blue')
PS> $data * 3
red
green
blue
red
green
blue
red
green
blue
0으로 초기화
일반적인 시나리오는 모든 0이 있는 배열을 만들려고 하는 것입니다. 정수만 사용하는 경우, 강하게 형식화된 정수 배열은 모두 0으로 초기화됩니다.
PS> [int[]]::new(4)
0
0
0
0
곱하기 트릭을 사용하여 이 작업을 수행할 수도 있습니다.
PS> $data = @(0) * 4
PS> $data
0
0
0
0
곱하기 트릭에 대한 좋은 점은 당신이 어떤 값을 사용할 수 있다는 것입니다. 따라서 기본값으로 사용 255
하려는 경우 이 작업을 수행하는 것이 좋습니다.
PS> $data = @(255) * 4
PS> $data
255
255
255
255
중첩된 배열
배열 내의 배열을 중첩된 배열이라고 합니다. PowerShell에서는 이러한 기능을 많이 사용하지 않지만 다른 언어로 더 많이 사용했습니다. 데이터가 그리드 패턴에 맞는 경우 배열의 배열을 사용하는 것이 좋습니다.
다음은 2차원 배열을 만들 수 있는 두 가지 방법입니다.
$data = @(@(1,2,3),@(4,5,6),@(7,8,9))
$data2 = @(
@(1,2,3),
@(4,5,6),
@(7,8,9)
)
이러한 예제에서는 쉼표가 매우 중요합니다. 쉼표가 선택 사항인 여러 줄에서 일반 배열의 이전 예제를 제공했습니다. 다차원 배열의 경우는 그렇지 않습니다.
인덱스 표기법을 사용하는 방식은 이제 중첩된 배열이 있으므로 약간 변경됩니다. 위의 값을 $data
사용하여 값 3에 액세스하는 방법입니다.
PS> $outside = 0
PS> $inside = 2
PS> $data[$outside][$inside]
3
배열 중첩의 각 수준에 대괄호 집합을 추가합니다. 첫 번째 대괄호 집합은 가장 바깥쪽 배열에 대한 것입니다. 그런 다음 거기에서부터 내부로 작업을 진행합니다.
Write-Output -NoEnumerate
PowerShell은 배열의 래프 해제 또는 열거를 좋아합니다. 이는 PowerShell에서 파이프라인을 사용하는 방식의 핵심 측면이지만 이러한 문제가 발생하지 않도록 하려는 경우가 있습니다.
나는 일반적으로 개체에 대해 자세히 알아보기 위해 개체를 Get-Member
파이프합니다. 배열을 파이핑하면 해제가 되어 Get-Member는 실제 배열이 아닌 배열의 구성원을 보게 됩니다.
PS> $data = @('red','green','blue')
PS> $data | Get-Member
TypeName: System.String
...
배열의 언래핑을 방지하려면 Write-Output -NoEnumerate
를 사용할 수 있습니다.
PS> Write-Output -NoEnumerate $data | Get-Member
TypeName: System.Object[]
...
나는 별로 바람직하지 않은 해킹 같은 방법이 하나 더 있긴 한데, 이런 해킹은 피하려고 노력한다. 배열을 파이프라인으로 넘기기 전에, 배열 앞에 쉼표를 배치할 수 있습니다. 이는 $data
이 유일한 요소인 다른 배열로 래핑되어 있으므로, 외부 배열을 해제하면 $data
을 다시 얻습니다.
PS> ,$data | Get-Member
TypeName: System.Object[]
...
배열 반환
이러한 배열 래핑 해제는 함수에서 값을 출력하거나 반환할 때도 발생합니다. 변수를 사용하여 출력을 할당하면 배열을 여전히 얻을 수 있으며, 이는 일반적으로 문제가 되지 않습니다.
문제는 새 배열이 있다는 것입니다. 문제가 있는 경우, Write-Output -NoEnumerate $array
또는 return ,$array
를 사용하여 이를 해결할 수 있습니다.
다른 것?
받아들이기 힘들다는 걸 알아. 내 희망은 당신이 그것을 읽을 때마다이 문서에서 뭔가를 배우고 그것은 앞으로 오랜 시간 동안 당신을위한 좋은 참조로 판명되는 것입니다. 도움이 된다면 가치를 얻을 수 있다고 생각하는 다른 사용자와 공유하세요.
제가 쓴 해시 테이블에 관한 비슷한 게시물을 여기에서 확인해 보시는 것을 추천합니다.
PowerShell