循环散列,或使用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 }