PSCustomObject PowerShell 도구 벨트에 추가하는 데 유용한 도구입니다. 기본 사항부터 시작하여 고급 기능을 살펴보겠습니다.
PSCustomObject 사용하는 방법은 구조화된 데이터를 만드는 간단한 방법을 사용하는 것입니다. 첫 번째 예제를 살펴보면 그 의미를 더 잘 알 수 있습니다.
비고
이 문서의 원래 버전@KevinMarquette작성한 블로그에 나타났습니다. PowerShell 팀은 이 콘텐츠를 공유해 주신 Kevin에게 감사드립니다. PowerShellExplained.com자신의 블로그를 확인하세요.
PSCustomObject 만들기
저는 PowerShell에서 [pscustomobject] 사용하는 것을 좋아합니다. 사용 가능한 개체를 만드는 것이 더 쉬워졌습니다.
따라서 개체를 만들 수 있는 다른 모든 방법을 건너뛰려고 하지만 이러한 예제의 대부분은 PowerShell v3.0 이상임을 언급해야 합니다.
$myObject = [pscustomobject]@{
Name = 'Kevin'
Language = 'PowerShell'
State = 'Texas'
}
이 메서드는 거의 모든 것에 대해 해시 테이블을 사용하기 때문에 잘 작동합니다. 하지만 PowerShell에서 해시 테이블을 개체처럼 취급하려고 하는 경우가 있습니다. 첫 번째 차이점은 Format-Table 또는 Export-Csv 사용하려는 경우이며 해시 테이블은 키/값 쌍의 컬렉션일 뿐입니다.
그런 다음 일반 개체와 같은 값에 액세스하고 사용할 수 있습니다.
$myObject.Name
해시 테이블 변환
말이 나온 김에, 이 작업을 수행할 수 있다는 것을 아시나요?
$myHashtable = @{
Name = 'Kevin'
Language = 'PowerShell'
State = 'Texas'
}
$myObject = [pscustomobject]$myHashtable
처음부터 개체를 만드는 것을 선호하지만 먼저 해시 테이블을 사용해야 하는 경우가 있습니다. 이 예제는 생성자가 개체 속성에 대한 해시 테이블을 사용하므로 작동합니다. 한 가지 중요한 점은 이 메서드가 작동하지만 정확히 동일하지는 않다는 것입니다. 가장 큰 차이점은 속성의 순서가 유지되지 않는다는 것입니다.
순서를 유지하려면 정렬된 해시 테이블을참조하세요.
기존의 접근 방식
사용자가 New-Object 사용하여 사용자 지정 개체를 만드는 것을 보았을 수 있습니다.
$myHashtable = @{
Name = 'Kevin'
Language = 'PowerShell'
State = 'Texas'
}
$myObject = New-Object -TypeName psobject -Property $myHashtable
이 방법은 상당히 느리지만 PowerShell의 초기 버전에서 가장 좋은 옵션일 수 있습니다.
파일에 저장
파일에 해시 테이블을 저장하는 가장 좋은 방법은 JSON으로 저장하는 것입니다.
[pscustomobject]으로 다시 가져올 수 있습니다.
$myObject | ConvertTo-Json -Depth 1 | Set-Content -Path $Path
$myObject = Get-Content -Path $Path | ConvertFrom-Json
파일에 개체를 저장하는 더 많은 방법을 다룹니다.파일을 읽고 쓰는 여러 가지 방법이 있습니다.
속성 작업
속성 추가
Add-Member을 사용하여 PSCustomObject에 새 속성을 추가할 수 있습니다.
$myObject | Add-Member -MemberType NoteProperty -Name 'ID' -Value 'KevinMarquette'
$myObject.ID
속성 제거
개체에서 속성을 제거할 수도 있습니다.
$myObject.psobject.Properties.Remove('ID')
.psobject 기본 개체 메타데이터에 대한 액세스를 제공하는 내장 멤버입니다. 내장 멤버에 대한 자세한 내용은 about_Intrinsic_Members참조하세요.
속성 이름을 열거하기
경우에 따라 개체의 모든 속성 이름 목록이 필요합니다.
$myObject | Get-Member -MemberType NoteProperty | select -ExpandProperty Name
psobject 속성에서 이 동일한 목록을 가져올 수도 있습니다.
$myobject.psobject.Properties.Name
비고
Get-Member 사전순으로 속성을 반환합니다. 멤버 액세스 연산자를 사용하여 속성 이름을 열거하면 개체에 정의된 순서대로 속성이 반환됩니다.
동적으로 속성에 액세스
속성 값에 직접 액세스할 수 있다고 이미 언급했습니다.
$myObject.Name
속성 이름에 문자열을 사용할 수 있으며 여전히 작동합니다.
$myObject.'Name'
이 한 단계를 더 수행하고 속성 이름에 변수를 사용할 수 있습니다.
$property = 'Name'
$myObject.$property
나는 그것이 이상하게 보인다는 것을 알고 있지만 작동합니다.
PSCustomObject를 해시 테이블로 변환
마지막 섹션에서 계속하려면 속성을 동적으로 탐색하고 해당 속성에서 해시 테이블을 만들 수 있습니다.
$hashtable = @{}
foreach( $property in $myobject.psobject.Properties.Name )
{
$hashtable[$property] = $myObject.$property
}
속성 테스트
속성이 있는지 알아야 하는 경우 해당 속성에 값이 있는지 확인할 수 있습니다.
if( $null -ne $myObject.ID )
값이 $null일 수 있는지 확인하려면, psobject.Properties을 조사하여 값이 존재하는지 확인할 수 있습니다.
if( $myobject.psobject.Properties.Match('ID').Count )
개체 메서드 추가
개체에 스크립트 메서드를 추가해야 하는 경우 Add-Member 및 ScriptBlock사용하여 수행할 수 있습니다. 현재 개체를 참조하는 this 자동 변수를 사용해야 합니다. 다음은 개체를 해시테이블로 전환하는 scriptblock입니다. (마지막 예제와 동일한 코드가 형성됨)
$ScriptBlock = {
$hashtable = @{}
foreach( $property in $this.psobject.Properties.Name )
{
$hashtable[$property] = $this.$property
}
return $hashtable
}
그런 다음 스크립트 속성으로 개체에 추가합니다.
$memberParam = @{
MemberType = "ScriptMethod"
InputObject = $myobject
Name = "ToHashtable"
Value = $scriptBlock
}
Add-Member @memberParam
그런 다음 다음과 같이 함수를 호출할 수 있습니다.
$myObject.ToHashtable()
개체 및 값 형식
개체 및 값 형식은 변수 할당을 동일한 방식으로 처리하지 않습니다. 값 형식을 서로 할당하면 값만 새 변수에 복사됩니다.
$first = 1
$second = $first
$second = 2
이 경우 $first 1이고 $second 2입니다.
개체 변수는 실제 개체에 대한 참조를 보유합니다. 새 변수에 하나의 개체를 할당하는 경우에도 동일한 개체를 참조합니다.
$third = [pscustomobject]@{Key=3}
$fourth = $third
$fourth.Key = 4
$third 및 $fourth 개체의 동일한 인스턴스를 참조하므로 $third.key 및 $fourth.Key 모두 4입니다.
psobject. Copy()
개체의 실제 복사본이 필요한 경우 복제할 수 있습니다.
$third = [pscustomobject]@{Key=3}
$fourth = $third.psobject.Copy()
$fourth.Key = 4
복제는 개체의 단순 복사본을 만듭니다. 현재 인스턴스가 다르고 $third.key 3이고 이 예제에서는 $fourth.Key 4입니다.
중첩된 개체(속성이 있는 개체에 다른 개체 포함)가 있는 경우 최상위 값만 복사되기 때문에 이 복사본을 단순 복사본이라고 합니다. 자식 개체는 서로 간에 참조합니다.
사용자 지정 개체 형식에 대한 PSTypeName
이제 우리가 개체를 가지고 있으므로, 개체로 할 수 있는 덜 명확한 몇 가지 추가적인 작업이 있습니다. 가장 먼저 해야 할 일은 PSTypeName를 주는 것입니다. 이것은 내가 사람들이 그것을 하는 가장 일반적인 방법입니다.
$myObject.psobject.TypeNames.Insert(0,"My.Object")
나는 최근에 레딧 사용자 u/markekraus로부터 이것을 하는 또 다른 방법을 알게 되었다. 인라인으로 정의할 수 있는 이 접근 방식에 대해 설명합니다.
$myObject = [pscustomobject]@{
PSTypeName = 'My.Object'
Name = 'Kevin'
Language = 'PowerShell'
State = 'Texas'
}
나는 이것이 언어에 얼마나 잘 맞는지 좋아합니다. 이제 적절한 형식 이름을 가진 개체가 있으므로 몇 가지 작업을 더 수행할 수 있습니다.
비고
PowerShell 클래스를 사용하여 사용자 지정 PowerShell 형식을 만들 수도 있습니다. 자세한 내용은 PowerShell 클래스 개요참조하세요.
DefaultPropertySet 사용(상세한 방법)
PowerShell은 기본적으로 표시할 속성을 결정합니다. 많은 네이티브 명령에는 많은 작업을 수행하는 .ps1xml서식 파일 있습니다. Boe Prox 의게시물에서, PowerShell만을 사용하여 사용자 지정 개체에서 이 작업을 수행할 수 있는 또 다른 방법이 있습니다. 사용할 수 있도록 MemberSet을 제공합니다.
$defaultDisplaySet = 'Name','Language'
$defaultDisplayPropertySet = New-Object System.Management.Automation.PSPropertySet('DefaultDisplayPropertySet',[string[]]$defaultDisplaySet)
$PSStandardMembers = [System.Management.Automation.PSMemberInfo[]]@($defaultDisplayPropertySet)
$MyObject | Add-Member MemberSet PSStandardMembers $PSStandardMembers
이제 내 개체가 셸에 떨어지면 기본적으로 해당 속성만 표시됩니다.
DefaultPropertySet을 사용하여 Update-TypeData
이 방법이 좋지만 최근에 Update-TypeData 사용하여 기본 속성을 지정하는 더 나은 방법을 보았습니다.
$TypeData = @{
TypeName = 'My.Object'
DefaultDisplayPropertySet = 'Name','Language'
}
Update-TypeData @TypeData
그것은 내가 빠른 참조로이 게시물을 가지고 있지 않은 경우 거의 기억할 수있을만큼 간단합니다. 속성이 많은 개체를 이제 쉽게 만들 수 있으며, 셸에서 이를 볼 때도 멋지고 깔끔한 보기를 유지할 수 있습니다. 다른 속성에 액세스하거나 확인해야 하는 경우 여전히 해당 속성이 있습니다.
$myObject | Format-List *
ScriptProperty를 사용하여 Update-TypeData
또한 그 비디오에서 알아낸 것은 객체에 대한 스크립트 속성을 생성하는 방법이었습니다. 기존 개체에서도 작동한다는 점을 지적하기에 좋은 시기입니다.
$TypeData = @{
TypeName = 'My.Object'
MemberType = 'ScriptProperty'
MemberName = 'UpperCaseName'
Value = {$this.Name.ToUpper()}
}
Update-TypeData @TypeData
개체를 생성하기 전이나 후에 이 작업을 수행할 수 있으며, 계속 작동합니다. 이것이 스크립트 속성과 함께 Add-Member 사용하는 것과 다릅니다. 앞에서 참조한 방식으로 Add-Member 사용하면 개체의 특정 인스턴스에만 존재합니다. 이 TypeName있는 모든 개체에 적용됩니다.
함수 매개 변수
이제 함수 및 스크립트의 매개 변수에 이러한 사용자 지정 형식을 사용할 수 있습니다. 한 함수가 이러한 사용자 지정 개체를 만든 다음 다른 함수에 전달하게 할 수 있습니다.
param( [PSTypeName('My.Object')]$Data )
PowerShell은 개체가 지정된 형식이어야 한다고 요구합니다. 형식이 자동으로 일치하지 않으면, 코드에서 이를 테스트할 필요 없이 유효성 검사 오류가 발생합니다. PowerShell이 가장 잘하는 작업을 수행하도록 하는 좋은 예입니다.
함수 출력형식
고급 함수에 대한 OutputType 정의할 수도 있습니다.
function Get-MyObject
{
[OutputType('My.Object')]
[CmdletBinding()]
param
(
...
OutputType 특성 값은 설명서 참고 사항일 뿐입니다. 함수 코드에서 파생되거나 실제 함수 출력과 비교되지 않습니다.
출력 형식을 사용하는 주된 이유는 함수에 대한 메타 정보가 의도를 반영하기 때문입니다.
Get-Command 및 Get-Help과 같은 요소를 개발 환경에서 활용할 수 있습니다. 추가 정보가 필요하다면, 해당 항목에 대한 도움말을 참고하세요: about_Functions_OutputTypeAttribute.
즉, Pester를 사용하여 함수를 단위 테스트하는 경우 출력 개체가 OutputType일치하는지 확인하는 것이 좋습니다. 이렇게 하면 파이프에 떨어지지 않아야 하는 변수를 잡을 수 있습니다.
맺음말
이 컨텍스트는 [pscustomobject]관한 것이었지만, 이 정보의 대부분은 일반적으로 개체에 적용됩니다.
나는 대부분의 이러한 기능을 전에 스쳐 지나가는 동안 본 적이 있지만, PSCustomObject에 대한 정보의 컬렉션으로는 본 적이 없다. 지난주 나는 다른 하나를 우연히 발견하고 그것을 전에 보지 못했다는 것에 놀랐다. 제가 이 모든 아이디어를 함께 모아서, 여러분이 전체적인 그림을 이해하시고, 이를 활용할 기회를 얻었을 때 인식할 수 있기를 바랍니다. 당신이 뭔가를 배우고, 그것을 스크립트에 적용할 방법을 찾기를 바랍니다.
PowerShell