Używam tego (uproszczonego) fragmentu kodu do wyodrębnienia zestawu tabel z SQL Server z 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
}
Działa świetnie, ale teraz niektóre tabele muszą zostać wyodrębnione za pomocą widoków, a niektóre nie. Więc potrzebuję struktury danych podobnej do tej:
"Page" "vExtractPage"
, "ChecklistItemCategory" "ChecklistItemCategory"
, "ChecklistItem" "vExtractChecklistItem"
Patrzyłem na skróty, ale nie znajduję nic o tym, jak zapętlić hash. Co należałoby tutaj zrobić? Może po prostu użyj tablicy, ale z obiema wartościami oddzielonymi spacją?
A może brakuje mi czegoś oczywistego?
powershell
Sylvia
źródło
źródło
$hash.Item($_)
zamiast$hash[$_]
?$hash.$_
.Stenografia nie jest preferowana w przypadku skryptów; jest mniej czytelny. Operator% {} jest uważany za skrótowy. Oto, jak należy to zrobić w skrypcie, aby zapewnić czytelność i możliwość ponownego użycia:
Zmienna konfiguracja
PS> $hash = @{ a = 1 b = 2 c = 3 } PS> $hash Name Value ---- ----- c 3 b 2 a 1
Opcja 1: GetEnumerator ()
Uwaga: osobiste preferencje; składnia jest łatwiejsza do odczytania
Metoda GetEnumerator () zostanie wykonana w następujący sposób:
foreach ($h in $hash.GetEnumerator()) { Write-Host "$($h.Name): $($h.Value)" }
Wynik:
Opcja 2: klucze
Metoda Keys zostanie wykonana w następujący sposób:
foreach ($h in $hash.Keys) { Write-Host "${h}: $($hash.Item($h))" }
Wynik:
Dodatkowe informacje
Uważaj, sortując swój hashtable ...
Sort-Object może zmienić to na tablicę:
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
To i inne pętle PowerShell są dostępne na moim blogu.
źródło
ForEach-Object
, który różni się odforeach
instrukcji tutaj.ForEach-Object
wykorzystuje potok, który może być znacznie szybszy, jeśli już pracujesz z potokiem.foreach
Oświadczenie nie robi; to prosta pętla.ForEach-Object
(aka:)%{}
jest szybsze niżforeach
; Pokazałem, że nie jest szybciej . Chciałem pokazać, czy twój punkt jest ważny, czy nie; ponieważ, jak większość ludzi, lubię, aby mój kod działał jak najszybciej. Teraz twoja argumentacja zmienia się na uruchamianie zadań równolegle (potencjalnie przy użyciu wielu komputerów / serwerów) ... co oczywiście jest szybsze niż uruchamianie zadań szeregowo z jednego wątku. Twoje zdrowie!Możesz to również zrobić bez zmiennej
@{ 'foo' = 222 'bar' = 333 'baz' = 444 'qux' = 555 } | % getEnumerator | % { $_.key $_.value }
źródło
O pętli przez hash:
$Q = @{"ONE"="1";"TWO"="2";"THREE"="3"} $Q.GETENUMERATOR() | % { $_.VALUE } 1 3 2 $Q.GETENUMERATOR() | % { $_.key } ONE THREE TWO
źródło
Oto inny szybki sposób, po prostu używając klucza jako indeksu do tabeli skrótów, aby uzyskać wartość:
$hash = @{ 'a' = 1; 'b' = 2; 'c' = 3 }; foreach($key in $hash.keys) { Write-Host ("Key = " + $key + " and Value = " + $hash[$key]); }
źródło
Preferuję ten wariant metody wyliczającej z potokiem, ponieważ nie musisz odwoływać się do tabeli skrótów w foreach (testowane w PowerShell 5):
$hash = @{ 'a' = 3 'b' = 2 'c' = 1 } $hash.getEnumerator() | foreach { Write-Host ("Key = " + $_.key + " and Value = " + $_.value); }
Wynik:
Teraz nie zostało to celowo posortowane według wartości, moduł wyliczający po prostu zwraca obiekty w odwrotnej kolejności.
Ale ponieważ jest to potok, mogę teraz sortować obiekty otrzymane z modułu wyliczającego według wartości:
$hash.getEnumerator() | sort-object -Property value -Desc | foreach { Write-Host ("Key = " + $_.key + " and Value = " + $_.value); }
Wynik:
źródło
$x = @{a = 1; z = 2}; $x.q = 3
jest „uporządkowany” jako q, a, z tutaj.[ordered]
atrybut uruchamia wybór innej implementacji.Jeśli używasz PowerShell v3, możesz użyć JSON zamiast tablicy haszującej i przekonwertować ją na obiekt z tablicy 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 }
źródło