我正在使用这个(简化的)代码块从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"
我在看哈希,但我找不到任何关于如何循环哈希的东西。这里做什么是正确的?也许只是使用一个数组,但两个值都用空格分隔?
或者我错过了一些明显的东西?
答案 0 :(得分:169)
脚本不喜欢速记;它的可读性较差。 %{}运算符被认为是简写。以下是如何在脚本中完成可读性和可重用性:
PS> $hash = @{
a = 1
b = 2
c = 3
}
PS> $hash
Name Value
---- -----
c 3
b 2
a 1
注:个人喜好;语法更容易阅读
GetEnumerator()方法将如下所示完成:
foreach ($h in $hash.GetEnumerator()) {
Write-Host "$($h.Name): $($h.Value)"
}
输出:
c: 3
b: 2
a: 1
Keys方法将如下所示完成:
foreach ($h in $hash.Keys) {
Write-Host "${h}: $($hash.Item($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
答案 1 :(得分:93)
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
答案 2 :(得分:5)
关于循环哈希:
$Q = @{"ONE"="1";"TWO"="2";"THREE"="3"}
$Q.GETENUMERATOR() | % { $_.VALUE }
1
3
2
$Q.GETENUMERATOR() | % { $_.key }
ONE
THREE
TWO
答案 3 :(得分:4)
您也可以在没有变量的情况下执行此操作
@{
'foo' = 222
'bar' = 333
'baz' = 444
'qux' = 555
} | % getEnumerator | % {
$_.key
$_.value
}
答案 4 :(得分:4)
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]);
}
答案 5 :(得分:3)
也可以使用子表达式运算符 $( ) 给出短遍历,它返回一个或多个语句的结果。
func didTapped(index: Int) {
index = index
}
结果:
$hash = @{ a = 1; b = 2; c = 3}
forEach($y in $hash.Keys){
Write-Host "$y -> $($hash[$y])"
}
答案 6 :(得分:2)
我更喜欢使用带有管道的枚举器方法的此变体,因为您不必在foreach中引用哈希表(在PowerShell 5中进行了测试):
Solarium library version: 3.0.0 - Ping query successful
Fatal error: Uncaught Solarium\Exception\UnexpectedValueException: Solr JSON response could not be decoded in C:\Bitnami\wampstack-7.0.0RC7-\apache2\htdocs\vendor\solarium\solarium\library\Solarium\Core\Query\Result\Result.php:158
Stack trace:
#0 C:\Bitnami\wampstack-7.0.0RC7-\apache2\htdocs\ping4.php(34): Solarium\Core\Query\Result\Result->getData()
#1 {main}
thrown in C:\Bitnami\wampstack-7.0.0RC7-\apache2\htdocs\vendor\solarium\solarium\library\Solarium\Core\Query\Result\Result.php on line 158
输出:
public static string SendRecOne(string dataToSvr)
{
TcpClient client = new TcpClient(SERVER_NAME, PORT);
#region SendRequest
int ByteCount = Encoding.ASCII.GetByteCount(dataToSvr); //How much bytes?
byte[] ByteBuffer = new byte[1024]; //initialize byte array
ByteBuffer = Encoding.ASCII.GetBytes(dataToSvr);
NetworkStream stream = client.GetStream();
stream.Write(ByteBuffer, 0, ByteBuffer.Length);
#endregion
#region Receive Response
//byte[] responseData = new byte[client.ReceiveBufferSize];
//int bytesRead = stream.Read(responseData, 0, client.ReceiveBufferSize);
int i;
string ToReturn = null;
ByteBuffer = new byte[ByteBuffer.Length];
MemoryStream ms = new MemoryStream();
while (true)
{
if (stream.DataAvailable)
{
while ((i = stream.Read(ByteBuffer, 0, ByteBuffer.Length)) != 0)
{
ms.Write(ByteBuffer, 0, ByteBuffer.Length);
if (stream.DataAvailable)
continue;
else
break;
}
ToReturn = Encoding.ASCII.GetString(ms.ToArray());
return ToReturn;
}
}
#endregion
现在,尚未对值进行故意排序,枚举器仅以相反的顺序返回对象。
但是,由于这是一条管道,因此我现在可以按值对从枚举器接收到的对象进行排序:
$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
答案 7 :(得分:1)
如果您使用的是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
}