Looping through a hash, or using an array in PowerShell

后端 未结 7 1596
暗喜
暗喜 2020-12-22 21:13

I\'m using this (simplified) chunk of code to extract a set of tables from SQL Server with BCP.

$OutputDirectory = \"c:\\junk\\\"
$ServerOption =   \"-SServe         


        
相关标签:
7条回答
  • 2020-12-22 21:17

    About looping through a hash:

    $Q = @{"ONE"="1";"TWO"="2";"THREE"="3"}
    $Q.GETENUMERATOR() | % { $_.VALUE }
    1
    3
    2
    
    $Q.GETENUMERATOR() | % { $_.key }
    ONE
    THREE
    TWO
    
    0 讨论(0)
  • 2020-12-22 21:32

    You can also do this without a variable

    @{
      'foo' = 222
      'bar' = 333
      'baz' = 444
      'qux' = 555
    } | % getEnumerator | % {
      $_.key
      $_.value
    }
    
    0 讨论(0)
  • 2020-12-22 21:35

    Here is another quick way, just using the key as an index into the hash table to get the value:

    $hash = @{
        'a' = 1;
        'b' = 2;
        'c' = 3
    };
    
    foreach($key in $hash.keys) {
        Write-Host ("Key = " + $key + " and Value = " + $hash[$key]);
    }
    
    0 讨论(0)
  • 2020-12-22 21:36

    Christian's answer works well and shows how you can loop through each hash table item using the GetEnumerator method. You can also loop through using the keys property. Here is an example how:

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

    Output:

    key = c , value = 3
    key = a , value = 1
    key = b , value = 2
    
    0 讨论(0)
  • 2020-12-22 21:37

    If you're using PowerShell v3, you can use JSON instead of a hashtable, and convert it to an object with 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
        }
    
    0 讨论(0)
  • 2020-12-22 21:38

    Shorthand is not preferred for scripts; it is less readable. The %{} operator is considered shorthand. Here's how it should be done in a script for readability and reusability:

    Variable Setup

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

    Option 1: GetEnumerator()

    Note: personal preference; syntax is easier to read

    The GetEnumerator() method would be done as shown:

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

    Output:

    c: 3
    b: 2
    a: 1
    

    Option 2: Keys

    The Keys method would be done as shown:

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

    Output:

    c: 3
    b: 2
    a: 1
    

    Additional information

    Be careful sorting your hashtable...

    Sort-Object may change it to an array:

    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
    

    This and other PowerShell looping are available on my blog.

    0 讨论(0)
提交回复
热议问题