Я использую этот (упрощенный) фрагмент кода для извлечения набора таблиц из 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"
Я смотрел хеши, но не нашел ничего о том, как их перебирать. Что было бы правильным здесь сделать? Возможно, просто использовать массив, но с обоими значениями, разделенными пробелом?
Или я упускаю что-то очевидное?
powershell
dictionary
hashtable
Сильвия
источник
источник
$hash.Item($_)
вместо$hash[$_]
?$hash.$_
.Сокращение не рекомендуется для скриптов; он менее читабелен. Оператор% {} считается сокращением. Вот как это должно быть сделано в скрипте для удобства чтения и повторного использования:
Настройка переменных
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)" }
Выход:
Вариант 2: ключи
Метод Keys будет выполнен, как показано:
foreach ($h in $hash.Keys) { Write-Host "${h}: $($hash.Item($h))" }
Выход:
Дополнительная информация
Будьте осторожны, сортируя хеш-таблицу ...
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 доступны в моем блоге.
источник
ForEach-Object
, который отличается от приведенногоforeach
здесь оператора.ForEach-Object
использует конвейер, что может быть намного быстрее, если вы уже работаете с конвейером. Вforeach
заявлении нет; это простой цикл.ForEach-Object
(он же:)%{}
быстрее, чемforeach
; Я показал, что не быстрее . Я хотел продемонстрировать, верна ваша точка зрения или нет; потому что мне, как и большинству людей, нравится, чтобы мой код выполнялся как можно быстрее. Теперь ваш аргумент меняется на параллельное выполнение заданий (потенциально с использованием нескольких компьютеров / серверов) ... что, конечно, быстрее, чем последовательное выполнение задания из одного потока. Ура!Вы также можете сделать это без переменной
@{ 'foo' = 222 'bar' = 333 'baz' = 444 'qux' = 555 } | % getEnumerator | % { $_.key $_.value }
источник
О цикле по хешу:
$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($key in $hash.keys) { Write-Host ("Key = " + $key + " and Value = " + $hash[$key]); }
источник
Я предпочитаю этот вариант метода перечислителя с конвейером, потому что вам не нужно обращаться к хеш-таблице в foreach (проверено в PowerShell 5):
$hash = @{ 'a' = 3 'b' = 2 'c' = 1 } $hash.getEnumerator() | foreach { Write-Host ("Key = " + $_.key + " and Value = " + $_.value); }
Выход:
Теперь, это не было намеренно отсортировано по значению, перечислитель просто возвращает объекты в обратном порядке.
Но поскольку это конвейер, теперь я могу отсортировать объекты, полученные от перечислителя, по значению:
$hash.getEnumerator() | sort-object -Property value -Desc | foreach { Write-Host ("Key = " + $_.key + " and Value = " + $_.value); }
Выход:
источник
$x = @{a = 1; z = 2}; $x.q = 3
здесь "упорядочено" как q, a, z.[ordered]
атрибут запускает выбор другой реализации.Если вы используете 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 }
источник