programing

해시 루프 또는 PowerShell 어레이 사용

yellowcard 2023. 4. 10. 21:33
반응형

해시 루프 또는 PowerShell 어레이 사용

BCP를 사용하여 SQL Server에서 테이블 세트를 추출합니다.

$OutputDirectory = 'c:\junk\'
$ServerOption =   "-SServerName"
$TargetDatabase = "Content.dbo."

$ExtractTables = @(
    "Page"
    , "ChecklistItemCategory"
    , "ChecklistItem"
)

for ($i=0; $i -le $ExtractTables.Length – 1; $i++)  {
    $InputFullTableName = "$TargetDatabase$($ExtractTables[$i])"
    $OutputFullFileName = "$OutputDirectory$($ExtractTables[$i])"
    bcp $InputFullTableName out $OutputFullFileName -T -c $ServerOption
}

이 기능은 훌륭하지만 현재 뷰에서 추출해야 하는 테이블과 그렇지 않은 테이블이 있습니다.따라서 다음과 같은 데이터 구조가 필요합니다.

"Page"                      "vExtractPage"
, "ChecklistItemCategory"   "ChecklistItemCategory"
, "ChecklistItem"           "vExtractChecklistItem"

해시를 보고 있었는데 해시를 어떻게 루핑해야 하는지 모르겠어요여기서 해야 할 일은 무엇일까요?두 값을 모두 공백으로 구분하여 어레이를 사용하면 어떨까요?

아니면 제가 뭔가를 놓치고 있는 건가요?

스크립트는 읽기 쉬우므로 생략은 권장되지 않습니다.%{} 연산자는 약자로 간주됩니다.가독성과 재사용성을 실현하기 위해 스크립트로 실행하는 방법은 다음과 같습니다.

변수 설정

PS> $hash = @{
    a = 1
    b = 2
    c = 3
}
PS> $hash

Name                           Value
----                           -----
c                              3
b                              2
a                              1

옵션 1: GetEnumerator()

주의: 개인 취향, 구문이 읽기 쉽습니다.

GetEnumerator() 메서드는 다음과 같이 실행됩니다.

foreach ($h in $hash.GetEnumerator()) {
    Write-Host "$($h.Name): $($h.Value)"
}

출력:

c: 3
b: 2
a: 1

옵션 2: 키

Keys 메서드는 다음과 같이 수행됩니다.

foreach ($h in $hash.Keys) {
    Write-Host "${h}: $($hash.$h)"
}

출력:

c: 3
b: 2
a: 1

추가 정보

해시 테이블을 정렬할 때 주의하세요.

Sort-Object에서 배열로 변경할 수 있습니다.

PS> $hash.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Hashtable                                System.Object


PS> $hash = $hash.GetEnumerator() | Sort-Object Name
PS> $hash.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array

이것과 다른 PowerShell 루핑은 제 블로그에서 볼 수 있습니다.

Christian의 답변은 잘 작동하며 각 해시 테이블 항목을 어떻게 루프할 수 있는지 보여줍니다.GetEnumerator방법.를 사용하여 루프 스루 할 수도 있습니다.keys소유물.다음은 예를 제시하겠습니다.

$hash = @{
    a = 1
    b = 2
    c = 3
}
$hash.Keys | % { "key = $_ , value = " + $hash.Item($_) }

출력:

key = c , value = 3
key = a , value = 1
key = b , value = 2

변수 없이 이 작업을 수행할 수도 있습니다.

@{
  'foo' = 222
  'bar' = 333
  'baz' = 444
  'qux' = 555
} | % getEnumerator | % {
  $_.key
  $_.value
}

파이프라인이 있는 열거자 방식에서 이 변종을 사용하는 것이 좋습니다. 이는 사용자가 foreach(PowerShell 5에서 테스트됨)의 해시 테이블을 참조할 필요가 없기 때문입니다.

$hash = @{
    'a' = 3
    'b' = 2
    'c' = 1
}
$hash.getEnumerator() | foreach {
    Write-Host ("Key = " + $_.key + " and Value = " + $_.value);
}

출력:

Key = c and Value = 1
Key = b and Value = 2
Key = a and Value = 3

이것은 의도적으로 값을 기준으로 정렬된 것이 아닙니다. 열거자는 단순히 개체를 역순으로 반환합니다.

그러나 이것은 파이프라인이기 때문에 열거자로부터 받은 오브젝트를 값에 따라 정렬할 수 있습니다.

$hash.getEnumerator() | sort-object -Property value -Desc | foreach {
  Write-Host ("Key = " + $_.key + " and Value = " + $_.value);
}

출력:

Key = a and Value = 3
Key = b and Value = 2
Key = c and Value = 1

해시 테이블의 인덱스로서 키를 사용하여 값을 취득하는 또 다른 간단한 방법이 있습니다.

$hash = @{
    'a' = 1;
    'b' = 2;
    'c' = 3
};

foreach($key in $hash.keys) {
    Write-Host ("Key = " + $key + " and Value = " + $hash[$key]);
}

해시를 통한 루프에 대해서:

$Q = @{"ONE"="1";"TWO"="2";"THREE"="3"}
$Q.GETENUMERATOR() | % { $_.VALUE }
1
3
2

$Q.GETENUMERATOR() | % { $_.key }
ONE
THREE
TWO

하나 이상의 문의 결과를 반환하는 하위 표현식 연산자 $()를 사용하여 짧은 트래버스를 제공할 수도 있습니다.

$hash = @{ a = 1; b = 2; c = 3}

forEach($y in $hash.Keys){
    Write-Host "$y -> $($hash[$y])"
}

결과:

a -> 1
b -> 2
c -> 3

PowerShell v3을 사용하는 경우 해시 테이블 대신 JSON을 사용하여 Convert-FromJson을 사용하여 개체로 변환할 수 있습니다.

@'
[
    {
        FileName = "Page";
        ObjectName = "vExtractPage";
    },
    {
        ObjectName = "ChecklistItemCategory";
    },
    {
        ObjectName = "ChecklistItem";
    },
]
'@ | 
    Convert-FromJson |
    ForEach-Object {
        $InputFullTableName = '{0}{1}' -f $TargetDatabase,$_.ObjectName

        # In strict mode, you can't reference a property that doesn't exist, 
        #so check if it has an explicit filename firest.
        $outputFileName = $_.ObjectName
        if( $_ | Get-Member FileName )
        {
            $outputFileName = $_.FileName
        }
        $OutputFullFileName = Join-Path $OutputDirectory $outputFileName

        bcp $InputFullTableName out $OutputFullFileName -T -c $ServerOption
    }

언급URL : https://stackoverflow.com/questions/9015138/looping-through-a-hash-or-using-an-array-in-powershell

반응형