Minden, amit tudni akart a switch utasításról

Sok más nyelvhez hasonlóan a PowerShell is rendelkezik parancsokkal a végrehajtás folyamatának vezérléséhez a szkripteken belül. Az egyik ilyen utasítás a switch utasítás, és a PowerShellben olyan funkciókat kínál, amelyek más nyelveken nem találhatók meg. A mai napon részletesen foglalkozunk a PowerShell használatával switch.

Megjegyzés

A cikk eredeti verziója@KevinMarquette által írt blogban jelent meg. A PowerShell csapata köszönjük Kevinnek, hogy megosztotta velünk ezt a tartalmat. Kérjük, nézd meg a blog PowerShellExplained.com.

Az if utasítás

Az első megtanult állítások egyike az if utasítás. Ez lehetővé teszi egy szkriptblokk végrehajtását, ha egy utasítás .$true

if ( Test-Path $Path )
{
    Remove-Item $Path
}

Sokkal bonyolultabb logikával elseif és else utasításokkal rendelkezhet. Íme egy példa, amelyben a hét napjának numerikus értéke van, és sztringként szeretném megkapni a nevet.

$day = 3

if ( $day -eq 0 ) { $result = 'Sunday'        }
elseif ( $day -eq 1 ) { $result = 'Monday'    }
elseif ( $day -eq 2 ) { $result = 'Tuesday'   }
elseif ( $day -eq 3 ) { $result = 'Wednesday' }
elseif ( $day -eq 4 ) { $result = 'Thursday'  }
elseif ( $day -eq 5 ) { $result = 'Friday'    }
elseif ( $day -eq 6 ) { $result = 'Saturday'  }

$result
Wednesday

Kiderült, hogy ez egy gyakori minta, és ennek számos módja van. Az egyik a switch.

Switch utasítás

Az switch utasítás lehetővé teszi egy változó és a lehetséges értékek listájának megadását. Ha az érték megegyezik a változóval, akkor a szkriptblokk végrehajtása történik.

$day = 3

switch ( $day )
{
    0 { $result = 'Sunday'    }
    1 { $result = 'Monday'    }
    2 { $result = 'Tuesday'   }
    3 { $result = 'Wednesday' }
    4 { $result = 'Thursday'  }
    5 { $result = 'Friday'    }
    6 { $result = 'Saturday'  }
}

$result
'Wednesday'

Ebben a példában az érték $day megfelel az egyik numerikus értéknek, majd a megfelelő nevet rendeli hozzá $result. Ebben a példában csak változó-hozzárendelést végzünk, de bármely PowerShell végrehajtható ezekben a szkriptblokkokban.

Hozzárendelés változóhoz

Ezt az utolsó példát más módon is megírhatjuk.

$result = switch ( $day )
{
    0 { 'Sunday'    }
    1 { 'Monday'    }
    2 { 'Tuesday'   }
    3 { 'Wednesday' }
    4 { 'Thursday'  }
    5 { 'Friday'    }
    6 { 'Saturday'  }
}

Az értéket a PowerShell-folyamatra helyezzük, és hozzárendeljük a $result. Ugyanezt megteheti az és foreach az if állításokkal is.

Alapértelmezett

A kulcsszóval default azonosíthatjuk, hogy mi történjen, ha nincs egyezés.

$result = switch ( $day )
{
    0 { 'Sunday' }
    # ...
    6 { 'Saturday' }
    default { 'Unknown' }
}

Itt az alapértelmezett esetben adjuk vissza az értéket Unknown .

Sztringek

Az előző példákban a számokat egyeztettem, de sztringeket is egyeztethet.

$item = 'Role'

switch ( $item )
{
    Component
    {
        'is a component'
    }
    Role
    {
        'is a role'
    }
    Location
    {
        'is a location'
    }
}
is a role

Úgy döntöttem, hogy nem burkoljuk a Component,Role és Location a találatok idézőjelek itt kiemelni, hogy nem kötelező. Ezeket switch a legtöbb esetben sztringként kezeli.

Tömbök

A PowerShell switch egyik ritka funkciója a tömbök kezelése. Ha megad egy switch tömböt, az a gyűjtemény minden elemét feldolgozza.

$roles = @('WEB','Database')

switch ( $roles ) {
    'Database'   { 'Configure SQL' }
    'WEB'        { 'Configure IIS' }
    'FileServer' { 'Configure Share' }
}
Configure IIS
Configure SQL

Ha ismétlődő elemek vannak a tömbben, akkor a megfelelő szakasz többször is megfelelteti őket.

PSItem

A feldolgozott aktuális elemre $PSItem hivatkozhat, vagy $_ hivatkozhat rá. Ha egyszerű egyezést hajtunk végre, az az érték, $PSItem amelyet egyeztetünk. A következő szakaszban speciális egyezéseket fogok végrehajtani, ahol ezt a változót használjuk.

Paraméterek

A PowerShell switch egyik egyedi funkciója, hogy számos kapcsolóparaméterrel rendelkezik, amelyek megváltoztatják a teljesítményét.

-CaseSensitive

Az egyezések alapértelmezés szerint nem érzékenyek a kis- és nagybetűkre. Ha a kis- és nagybetűk megkülönböztetésére van szükség, használhatja -CaseSensitivea következőt: Ez a többi kapcsolóparaméterrel együtt használható.

-Helyettesítő

A kapcsolóval engedélyezhetjük a -wildcard helyettesítő karakterek támogatását. Ez ugyanazt a helyettesítő karakteres logikát használja, mint az operátor az -like egyes egyezések elvégzéséhez.

$Message = 'Warning, out of disk space'

switch -Wildcard ( $message )
{
    'Error*'
    {
        Write-Error -Message $Message
    }
    'Warning*'
    {
        Write-Warning -Message $Message
    }
    default
    {
        Write-Information $message
    }
}
WARNING: Warning, out of disk space

Itt egy üzenetet dolgozunk fel, majd a tartalom alapján különböző streameken küldjük ki.

-Regex

A switch utasítás ugyanúgy támogatja a regex egyezéseket, mint a helyettesítő karaktereket.

switch -Regex ( $message )
{
    '^Error'
    {
        Write-Error -Message $Message
    }
    '^Warning'
    {
        Write-Warning -Message $Message
    }
    default
    {
        Write-Information $message
    }
}

Van több példa a regex használatára egy másik cikkben írtam: A regex használatának számos módja.

-Fájl

A switch utasítás egyik kevéssé ismert funkciója, hogy képes feldolgozni egy fájlt a -File paraméterrel. Ahelyett, hogy változókifejezést ad neki, egy fájl elérési útját használja -file .

switch -Wildcard -File $path
{
    'Error*'
    {
        Write-Error -Message $PSItem
    }
    'Warning*'
    {
        Write-Warning -Message $PSItem
    }
    default
    {
        Write-Output $PSItem
    }
}

Ugyanúgy működik, mint egy tömb feldolgozása. Ebben a példában a helyettesítő karakterek egyeztetésével kombinálom, és a $PSItem. Ez feldolgozna egy naplófájlt, és a regex egyezéstől függően figyelmeztető és hibaüzenetekké alakítaná át.

Speciális részletek

Most, hogy megismerte ezeket a dokumentált funkciókat, a fejlettebb feldolgozás kontextusában használhatjuk őket.

Kifejezések

A switch változók helyett egy kifejezésen is szerepelhetnek.

switch ( ( Get-Service | Where status -eq 'running' ).name ) {...}

Bármit is értékel ki a kifejezés, az az egyezéshez használt érték.

Több egyezés

Lehet, hogy már felvette ezt a műveletet, de a feltételek switch több feltételnek is megfelelhetnek. Ez különösen igaz, ha használja -wildcard vagy -regex egyezik. Ugyanazt a feltételt többször is hozzáadhatja, és mindegyik aktiválódik.

switch ( 'Word' )
{
    'word' { 'lower case word match' }
    'Word' { 'mixed case word match' }
    'WORD' { 'upper case word match' }
}
lower case word match
mixed case word match
upper case word match

Mind a három állítás ki van rúgva. Ez azt mutatja, hogy minden feltétel (sorrendben) be van jelölve. Ez igaz a tömbök feldolgozására, ahol minden elem ellenőrzi az egyes feltételeket.

Folytatás

Általában itt mutatnám be az break állítást, de jobb, ha megtanuljuk, hogyan kell először használni continue . Csakúgy, mint egy foreach hurok, continue továbbra is a következő elem a gyűjteményben, vagy kilép a switch , ha nincs több elem. Az utolsó példát újraírhatjuk folytatási utasításokkal, hogy csak egy utasítás legyen végrehajtva.

switch ( 'Word' )
{
    'word'
    {
        'lower case word match'
        continue
    }
    'Word'
    {
        'mixed case word match'
        continue
    }
    'WORD'
    {
        'upper case word match'
        continue
    }
}
lower case word match

Ahelyett, hogy mindhárom elemet egyezteti, a rendszer az elsőt egyezteti, és a kapcsoló a következő értékre folytatódik. Mivel nincsenek feldolgozandó értékek, a kapcsoló kilép. Ez a következő példa azt mutatja be, hogy egy helyettesítő karakter hogyan felelhet meg több elemnek.

switch -Wildcard -File $path
{
    '*Error*'
    {
        Write-Error -Message $PSItem
        continue
    }
    '*Warning*'
    {
        Write-Warning -Message $PSItem
        continue
    }
    default
    {
        Write-Output $PSItem
    }
}

Mivel a bemeneti fájl egy sora a szót és Warninga szót Error is tartalmazhatja, csak az elsőt szeretnénk végrehajtani, majd folytatni a fájl feldolgozását.

Felosztás

Egy break utasítás kilép a kapcsolóból. Ez ugyanaz a viselkedés, mint az continue egyetlen érték esetében. A különbség tömb feldolgozásakor jelenik meg. break leállítja a kapcsoló összes feldolgozását, és continue a következő elemre kerül.

$Messages = @(
    'Downloading update'
    'Ran into errors downloading file'
    'Error: out of disk space'
    'Sending email'
    '...'
)

switch -Wildcard ($Messages)
{
    'Error*'
    {
        Write-Error -Message $PSItem
        break
    }
    '*Error*'
    {
        Write-Warning -Message $PSItem
        continue
    }
    '*Warning*'
    {
        Write-Warning -Message $PSItem
        continue
    }
    default
    {
        Write-Output $PSItem
    }
}
Downloading update
WARNING: Ran into errors downloading file
write-error -message $PSItem : Error: out of disk space
+ CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException

Ebben az esetben, ha olyan sorokat értünk el, amelyek kezdődnek Error , hibaüzenetet kapunk, és a kapcsoló leáll. Ez az, amit ez break a kijelentés tesz értünk. Ha nem csak az elején találjuk Error meg a sztringet, hanem figyelmeztetésként írjuk. Ugyanezt tesszük Warning. Lehetséges, hogy egy sornak a szó Error és Warninga szó is lehet, de csak egy kell a feldolgozáshoz. Ez az, amit a continue nyilatkozat tesz értünk.

Töréscímkék

Az switch utasítás ugyanúgy támogatja break/continue a címkéket, mint a foreach.

:filelist foreach($path in $logs)
{
    :logFile switch -Wildcard -File $path
    {
        'Error*'
        {
            Write-Error -Message $PSItem
            break filelist
        }
        'Warning*'
        {
            Write-Error -Message $PSItem
            break logFile
        }
        default
        {
            Write-Output $PSItem
        }
    }
}

Személy szerint nem szeretem a töréscímkék használatát, de fel akartam mutatni őket, mert zavaróak, ha még soha nem láttad őket. Ha több switch vagy foreach egymásba ágyazott utasítása van, érdemes lehet több elemből is kiszakadni, mint a legbelső elem. Elhelyezhet egy címkét egy switch olyan címkén, amely a cél lehet.break

Enumeráció

A PowerShell 5.0 enumerálásokat adott nekünk, és egy kapcsolóban használhatjuk őket.

enum Context {
    Component
    Role
    Location
}

$item = [Context]::Role

switch ( $item )
{
    Component
    {
        'is a component'
    }
    Role
    {
        'is a role'
    }
    Location
    {
        'is a location'
    }
}
is a role

Ha mindent szigorúan beírt számként szeretne tartani, akkor zárójelbe helyezheti őket.

switch ($item )
{
    ([Context]::Component)
    {
        'is a component'
    }
    ([Context]::Role)
    {
        'is a role'
    }
    ([Context]::Location)
    {
        'is a location'
    }
}

A zárójelekre azért van szükség, hogy a kapcsoló ne konstans sztringként kezelje az értéket [Context]::Location .

ScriptBlock

Szükség esetén szkriptblokk használatával elvégezhetjük egy egyezés kiértékelését.

$age = 37

switch ( $age )
{
    {$PSItem -le 18}
    {
        'child'
    }
    {$PSItem -gt 18}
    {
        'adult'
    }
}
'adult'

Ez összetettebbé teszi a dokumentumot, és megnehezítheti az switch olvasást. A legtöbb esetben, ha ehhez hasonlót használna, érdemesebb lenne az utasításokat és elseif az utasításokat használniif. Ezt akkor használnám, ha már volt egy nagy kapcsolóm, és két elemre volt szükségem ahhoz, hogy ugyanazt az értékelési blokkot elérhessem.

Egy dolog, ami szerintem segít az olvashatóságban, hogy zárójelbe kell tenni a scriptblockot.

switch ( $age )
{
    ({$PSItem -le 18})
    {
        'child'
    }
    ({$PSItem -gt 18})
    {
        'adult'
    }
}

Továbbra is ugyanúgy hajtja végre, és jobb vizuális szünetet biztosít, ha gyorsan megtekinti.

Regex $matches

Újra meg kell néznünk a regex-et, hogy megérintsünk valamit, ami nem azonnal nyilvánvaló. A regex használata feltölti a változót $matches . Én megy a használata $matches több, amikor beszélek a sok módja annak, hogy regex. Íme egy rövid példa, amely a nevesített egyezésekkel jeleníti meg működés közben.

$message = 'my ssn is 123-23-3456 and credit card: 1234-5678-1234-5678'

switch -regex ($message)
{
    '(?<SSN>\d\d\d-\d\d-\d\d\d\d)'
    {
        Write-Warning "message contains a SSN: $($matches.SSN)"
    }
    '(?<CC>\d\d\d\d-\d\d\d\d-\d\d\d\d-\d\d\d\d)'
    {
        Write-Warning "message contains a credit card number: $($matches.CC)"
    }
    '(?<Phone>\d\d\d-\d\d\d-\d\d\d\d)'
    {
        Write-Warning "message contains a phone number: $($matches.Phone)"
    }
}
WARNING: message may contain a SSN: 123-23-3456
WARNING: message may contain a credit card number: 1234-5678-1234-5678

$null

Olyan értékeket $null is egyeztethet, amelyeknek nem kell alapértelmezettnek lenniük.

$values = '', 5, $null
switch ( $values )
{
    $null          { "Value '$_' is `$null" }
    { '' -eq $_ }  { "Value '$_' is an empty string" }
    default        { "Value [$_] isn't an empty string or `$null" }
}
Value '' is an empty string
Value [5] isn't an empty string or $null
Value '' is $null

Amikor egy utasítás üres sztringjét switch teszteli, fontos, hogy a nyers érték ''helyett az ebben a példában látható összehasonlító utasítást használja. switch Egy utasításban a nyers érték '' is megegyezik $null. Például:

$values = '', 5, $null
switch ( $values )
{
    $null          { "Value '$_' is `$null" }
    ''             { "Value '$_' is an empty string" }
    default        { "Value [$_] isn't an empty string or `$null" }
}
Value '' is an empty string
Value [5] isn't an empty string or $null
Value '' is $null
Value '' is an empty string

Ügyeljen továbbá a parancsmagok üres visszatérési értékeivel is. A kimenet nélküli parancsmagokat vagy folyamatokat a rendszer üres tömbként kezeli, amely nem felel meg semminek, beleértve az esetet default is.

$file = Get-ChildItem NonExistantFile*
switch ( $file )
{
    $null   { '$file is $null' }
    default { "`$file is type $($file.GetType().Name)" }
}
# No matches

Állandó kifejezés

Lee Dailey rámutatott, hogy az elemek kiértékeléséhez [bool] használhatunk állandó $true kifejezést. Tegyük fel, hogy több logikai ellenőrzés is szükséges.

$isVisible = $false
$isEnabled = $true
$isSecure = $true

switch ( $true )
{
    $isEnabled
    {
        'Do-Action'
    }
    $isVisible
    {
        'Show-Animation'
    }
    $isSecure
    {
        'Enable-AdminMenu'
    }
}
Do-Action
Enabled-AdminMenu

Ez egy tiszta módszer több logikai mező állapotának kiértékelésére és végrehajtására. Az a jó ebben, hogy egy egyezés tükrözheti egy olyan érték állapotát, amely még nem lett kiértékelve.

$isVisible = $false
$isEnabled = $true
$isAdmin = $false

switch ( $true )
{
    $isEnabled
    {
        'Do-Action'
        $isVisible = $true
    }
    $isVisible
    {
        'Show-Animation'
    }
    $isAdmin
    {
        'Enable-AdminMenu'
    }
}
Do-Action
Show-Animation

Ebben $isEnabled a példában a $true beállítás azt is biztosítja, hogy $isVisible a beállítás értéke $trueis legyen. Ezután a kiértékeléskor $isVisible a szkriptblokk meg lesz hívva. Ez egy kicsit ellen-intuitív, de egy okos használata a mechanika.

automatikus változó $switch

Amikor a switch rendszer feldolgozza az értékeit, létrehoz egy enumerátort, és meghívja.$switch Ez a PowerShell által létrehozott automatikus változó, amelyet közvetlenül is kezelhet.

$a = 1, 2, 3, 4

switch($a) {
    1 { [void]$switch.MoveNext(); $switch.Current }
    3 { [void]$switch.MoveNext(); $switch.Current }
}

Ez a következő eredményekből ad eredményt:

2
4

Az enumerátor előremozdításával a következő elemet nem dolgozza fel a switch rendszer, de közvetlenül hozzáférhet az értékhez. Őrültnek nevezném.

Egyéb minták

Kivonattáblák

Az egyik legnépszerűbb álláshely az, amit tettem a hashtables. A keresési táblák egyik használati esete hashtable . Ez egy alternatív megközelítés egy olyan gyakori mintához, amelyet az switch állítások gyakran kezelnek.

$day = 3

$lookup = @{
    0 = 'Sunday'
    1 = 'Monday'
    2 = 'Tuesday'
    3 = 'Wednesday'
    4 = 'Thursday'
    5 = 'Friday'
    6 = 'Saturday'
}

$lookup[$day]
Wednesday

Ha csak keresésként használomswitch, gyakran használok helyette.hashtable

Enumeráció

Ebben az esetben a Enum PowerShell 5.0-s verzióval is bevezettük a megoldást.

$day = 3

enum DayOfTheWeek {
    Sunday
    Monday
    Tuesday
    Wednesday
    Thursday
    Friday
    Saturday
}

[DayOfTheWeek]$day
Wednesday

Egész nap megvizsgálhatnánk a probléma megoldásának különböző módjait. Csak biztos akartam lenni benne, hogy tudtál róla, hogy van lehetőséged.

Zárószavak

A switch utasítás egyszerű a felületen, de olyan speciális funkciókat kínál, amelyeket a legtöbb ember nem ismer fel. Ezeknek a funkcióknak a sztringezésével ez hatékony funkcióvá válik. Remélem, megtanultál valamit, amit még nem vettél észre.