循环散列,或使用PowerShell中的数组?

我正在使用这个(简化的)代码块从SQL Server中用bcp提取一组表。

$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" 

我正在看哈希,但我没有find任何关于如何通过哈希循环。 在这里做什么是正确的事情? 也许只是使用一个数组,但有两个值,用空格分开?

还是我错过了明显的东西?

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 

速记不是脚本的首选; 它不太可读。 %{}运算符被认为是简写。 以下是如何在脚本中完成可读性和可重用性:

variables设置

 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.Item($h))" } 

输出:

 c: 3 b: 2 a: 1 

附加信息

小心sorting你的散列表… sorting对象可能会将其更改为一个数组:

 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 

关于通过哈希循环:

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

你也可以做这个没有variables

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

下面是另一个快速的方法,只需使用密钥作为哈希表中的索引来获得值:

 $hash = @{ 'a' = 1; 'b' = 2; 'c' = 3 }; foreach($key in $hash.keys) { Write-Host ("Key = " + $key + " and Value = " + $hash[$key]); } 

如果您使用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 }