Articles

ForEach and Where magic methods

ForEach and Where are two frequently used concepts that have been available in PowerShell since version 1 came out in 2006. ForEach on ollut saatavilla sekä lausekkeena että cmdletinä (ForEach-Object), jonka avulla voit iteroida objektikokoelman läpi ja ryhtyä toimiin kerran kutakin kyseisen kokoelman objektia kohti. Missä on ollut saatavilla cmdlet (missä-objekti), jonka avulla voit suodattaa pois kohteita kokoelma, jotka eivät läpäise jokin ehto, ehto, joka voidaan arvioida käyttämällä joko ominaisuuksia esineitä kokoelma tai esineitä itse, jotka kuuluvat kokoelma. Foreachin kyky toimia kokoelman kohteissa ja missä kyky suodattaa kokoelma ovat ominaisuuksia, jotka ovat erittäin hyödyllisiä ja jotka sisältyvät muodossa tai toisessa logiikkaan monien PowerShell-skriptien, komentojen ja moduulien takana riippumatta siitä, mitä versiota Powershellista käytetään. Itse asiassa niitä käytetään niin paljon, että ne ovat olleet painopiste suorituskyvyn, toiminnallisuuden ja syntaksin parantamisessa PowerShell-versioissa 3.0 ja 4.0.

Windows PowerShell 4.0: n julkaisun myötä otettiin käyttöön kaksi uutta ”magic” – menetelmää kokoelmatyypeille, jotka tarjoavat uuden syntaksin Foreachin ja Where-ominaisuuksien käyttöön Windows Powershellissa. Nämä menetelmät ovat osuvasti nimetty ForEach ja missä. Kutsun näitä menetelmiä ”magiaksi”, koska ne ovat melko maagisia siinä, miten ne toimivat Powershellissa. Ne eivät näy Get-Member output, vaikka käytät-Force ja request-MemberType kaikki. Jos kääritään hihat ja kaivellaan pohdintaa, ne löytyvät; se vaatii kuitenkin laajaa hakua, koska ne ovat yksityisiä laajennusmenetelmiä, jotka on toteutettu yksityisellä luokalla. Vaikka niitä ei ole löydettävissä ilman peiton alle kurkistelua, ne ovat siellä, kun tarvitset niitä, ne ovat nopeampia kuin vanhemmat kollegansa, ja ne sisältävät toimintoja, joita ei ollut saatavilla vanhemmissa vastineissaan, joten ”maaginen” tunne, jonka ne jättävät sinulle, kun käytät niitä Powershellissa. Valitettavasti nämä menetelmät ovat edelleen paperittomia tänäkin päivänä, lähes vuosi sen jälkeen, kun ne julkaistiin julkisesti, joten monet ihmiset eivät tajua sitä voimaa, joka näissä menetelmissä on saatavilla. Tämä artikkeli yrittää korjata sen selittämällä, missä niitä voidaan käyttää ja miten ne toimivat, jotta voit hyödyntää tätä taikaa, kun käytät Powershellia.

huomautus PowerShell 3.0: sta

ennen kuin ryhdyn selittämään, miten ForEach ja missä menetelmät toimivat, minun on mainittava jotain näiden kahden menetelmän ja PowerShell 3.0: n suhteen. Vaikka on totta, että ForEach ja missä menetelmät olivat saatavilla vain PowerShell 4.0: ssa ja uudemmissa versioissa, PowerShell 3.0 on edelleen hyvin laajalti käytössä monissa ympäristöissä, ja ellet käytä Powershellia ympäristössä, joka on standardoitu PowerShell 4.0: ssa ja uudemmissa, saatat löytää itsesi haluamassa, että voisit hyödyntää uusien menetelmien tarjoamaa syntaksia PowerShell 3.0: n käytössä. Tunsin, että tämä oli rajoitus, jota kannattaa käsitellä, joten osana TypePx-moduulia, jonka olen äskettäin julkaissut GitHubissa ja PowerShell Resource galleriassa (alias PowerShellGet public repository, tällä hetkellä rajoitetussa esikatselussa), sisällytin Foreachin ja jossa komentosarjamenetelmät, jotka toiminnallisesti vastaavat PowerShell 4.0: ssa esitettyjä menetelmiä, jotta voit hyödyntää uutta syntaksia ja toiminnallisuutta, vaikka käyttäisit PowerShell 3.0: aa. Täytäntöönpanossa on muutamia puutteita, joita korostan myöhemmin tässä artikkelissa.

ForEach-menetelmä

ForEach on menetelmä, jonka avulla voidaan nopeasti iteroida läpi kokoelma objekteja ja tehdä jonkin verran toimia kunkin objektin kyseisessä kokoelmassa. Tämä menetelmä tarjoaa nopeamman suorituskyvyn kuin vanhemmat kollegansa (foreach lausuma ja ForEach-Object cmdlet), ja se myös yksinkertaistaa joitakin yleisimpiä toimia, jotka haluat ottaa esineitä kokoelma. Kaikki tällä menetelmällä tuotetut objektit palautetaan tyyppijärjestelmän yleisessä kokoelmassa.Kokoelma.Objektimalli.Kokoelma1.

tähän menetelmään voi vedota kuudella tuetulla tavalla, joista jokainen selitetään tarkemmin jäljempänä. ForEach-menetelmään vedottaessa voidaan käyttää seuraavia tuettuja argumentteja:

  • ForEach(scriptblock expression)
  • ForEach(type convertotype)
  • ForEach(string propertyName)
  • ForEach(string propertyName, object newValue)
  • ForEach(string methodName)
  • ForEach(string methodName, object arguments)
  • ForEach(scriptblock expression, object arguments)

huomaa, että nämä ovat tuettuja argumenttipareja, ei foreach-menetelmässä käytettävissä olevia erilaisia ylikuormituksia. Muiden kuin näiden argumenttiparien käyttäminen voi johtaa virheisiin, joissa ei selvästi tunnisteta, mikä todellinen ongelma on.

ForEach(scriptblock-lauseke) ja ForEach(scriptblock-lauseke, object-argumentit)

Jos siirrät komentosarjalohkon lausekkeen ForEach-menetelmään, pystyt suorittamaan samanlaisia tehtäviä kuin komentosarjalohkossa, jota käyttäisit foreach-lausekkeen tai ForEach-Object-cmdletin kanssa. Myös, kuten ForEach-objektin cmdlet, $ _ ja $PSItem-muuttujat viittaavat käsiteltävään kohteeseen. Kaikki argumentit, jotka annat alkuperäisen komentosarjalohkoargumentin lisäksi, käytetään komentosarjalohkon argumentteina. Tämä on aivan kuten miten-ArgumentList parametri toimii ForEach-objekti cmdlet. Tässä on esimerkki siitä, miten voit käyttää tätä komentosarjalohkon suorittamiseen jokaisella kokoelman kohteella:

# Get a set of services$services = Get-Service c*# Display the names and display names of all services in the collection$services.foreach{"$($_.Name) ($($_.DisplayName))"}# Select a property name to expand using a script block argument$services.foreach({param($PropertyName); $_.$PropertyName}, 'DisplayName')

olet saattanut huomata jotain outoa tässä syntaksissa, koska en käärinyt itse komentosarjalohkoa sulkeisiin. Voit kääriä sen sulkuihin, mutta se on vapaaehtoista PowerShell 4.0: ssa tai uudemmassa, koska PowerShell-jäsennintä parannettiin, jotta sulkeet voidaan jättää pois aina, kun vetoat menetelmään, joka hyväksyy yhden komentosarjalohkoargumentin. Myös, kuten foreach lausuma ja ForEach-Object cmdlet, script block että annat kutsutaan nykyisessä soveltamisalassa. Tämä tarkoittaa, että kaikki muuttuja tehtäviä teet sisällä että komentosarjalohko jatkuu sen jälkeen, kun ForEach menetelmä on päättynyt suorittamisen.

ForEach(type convertotype)

foreach-menetelmässä tyypin voi siirtää ForEach-menetelmään, jos haluaa muuntaa jokaisen kokoelman esineen toiseen tyyppiin. Kuvittele esimerkiksi, että sinulla on kokoelma esineitä ja haluat muuntaa nämä esineet niiden merkkijono vastaava. Tältä se näyttäisi ForEach-menetelmällä:

# Get a collection of processes$processes = Get-Process# Convert the objects in that collection into their string equivalent$processes.foreach()

saman tehtävän olisi voinut suorittaa lataamalla kokoelman tyyppijonoon (esim.] $prosesseihin), ja lataamalla sarjan on itse asiassa huomattavasti nopeampi, mutta on erittäin todennäköistä, ettet edes huomaisi eroa suoritusajassa ellet työskentelisi hyvin, hyvin suuren kokoelman kanssa. Huolimatta Aikaero, minulla on taipumus mieluummin ForEach menetelmä syntaksi tietyissä tilanteissa, jos se sallii minun säilyttää eleganssia toteutuksessa välttämällä ylimääräisiä sulkuja skriptejä kirjoitan.

ForEach(string propertyName)

PowerShell 3.0: ssa ja myöhemmin foreach-objektiin lisättiin toinen parametrijoukko, jonka avulla voit helpommin hakea tietyn ominaisuuden arvon yksinkertaisesti syöttämällä ominaisuuden nimen ForEach-objektin ainoaksi parametriarvoksi. Tätä mukavuutta on tarjottu myös ForEach-menetelmällä. Tässä on esimerkki, joka osoittaa, miten voit iteroida kokoelman läpi ja palauttaa kyseisen kokoelman ominaisuuden:

# Get all services whose name starts with "w"$services = Get-Service w*# Return the names of those services$services.foreach('Name')

tietenkin PowerShellin version 3.0 jälkeen voit yksinkertaisesti vedota $services.Name saadaksesi kaikkien palveluiden nimet, ja se valmistuu nopeammin kuin ForEach method-vaihtoehto (vaikka huomaat vain suorituskykyeron hyvin suurissa kokoelmissa satojentuhansien esineiden järjestyksessä); tämä toimii kuitenkin vain ominaisuuksille, jotka eivät ole itse kokoelmassa, ja se on syntaksi, johon jotkut skriptit eivät ole tyytyväisiä komennon implisiittisen luonteen vuoksi. Uusi ForEach method syntaksi tarjoaa sinulle selkeämmän vaihtoehdon, jonka lisäetuna on olla myös hieman itsedokumentoiva.

ForEach(string propertyName, object newValue)

ei ainoastaan voi hakea ominaisuutta esinekokoelmasta, voit asettaa ominaisuuden myös esinekokoelmasta. Tämä on toiminnallisuus, joka ei ole käytettävissä muissa foreach ’ s, ellet nimenomaisesti luoda script lohko tehdä niin. Määrittääksesi ominaisuuden, annat vain ominaisuuden nimen ja arvon, jota haluat käyttää määrittäessäsi kyseistä ominaisuutta, näin:

# Note, this is not a realistic example# This would be used more commonly on configuration data$services = Get-Service c*# Now change the display names of every service to some new value$services.foreach('DisplayName','Hello')

aivan kuten tehtävät tekisit käyttämällä equals-operaattoria, PowerShell yrittää muuntaa mitä tahansa annat uudeksi arvoksi sopivaan tyyppiin annettavalle kiinteistölle.

ForEach(string methodName) ja ForEach(string methodName, object arguments)

käyttääksesi menetelmää, annat yksinkertaisesti metodin nimen ensimmäisenä argumenttina ja sitten kyseisen metodin argumentit toisena, kolmantena, neljäntenä jne. argumentti. Jos menetelmä ei ota mitään argumentteja, voit yksinkertaisesti siirtää menetelmän nimi ja se vedotaan ilman argumentteja. Tässä on esimerkki osoittaa, miten voit tappaa joukko prosesseja käynnissä tietyn ohjelman:

# Get all processes running Chrome$processes = Get-Process -Name Chrome# Now kill all of those processes$processes.foreach('Kill')

tässä on toinen esimerkki, tällä kertaa käyttäen menetelmää, jossa on argumentteja, ja osoittaen, miten voit varmistaa, että komennot noudattavat parhaita käytäntöjä käyttämällä sopivia nimiä ja peitenimiä yleisesti käytetyille parametreille:

# Get all commands that have a ComputerName parameter$cmds = Get-Command -ParameterName ComputerName# Now show a table making sure the parameter names and aliases are consistent$cmds.foreach('ResolveParameter','ComputerName') | Format-Table Name,Aliases

kuten näistä tuloksista näkyy, Tietokonenimien parametrien toteutuksessa on varmasti joitakin epäjohdonmukaisuuksia, jotka pitäisi korjata.

, joka kattaa kaikki foreach-menetelmässä tällä hetkellä käytettävissä olevat toiminnot. Kuten näette, ei ole paljon uusia toimintoja tarjotaan tässä menetelmässä, mutta syntaksin parannuksia, kun suoritat yksinkertainen tehtävä kokoelma esineitä ovat mukavia, ja ForEach menetelmä suorituskyvyn parannuksia verrattuna vastaava foreach lauseke ForEach-objekti putki ovat ehdottomasti tervetullut parannus samoin. Kun tämä selitys on poissa tieltä, siirrytään missä-menetelmään.

missä-menetelmä

missä on menetelmä, jolla voidaan suodattaa kokoelma olioita. Tämä on hyvin paljon kuin missä-objekti cmdlet, mutta missä menetelmä on myös kuten Select-objekti ja ryhmä-objekti samoin, sisältää useita lisäominaisuuksia, joita missä-objekti cmdlet ei natiivisti tue itse. Tämä menetelmä tarjoaa nopeamman suorituskyvyn kuin missä-objekti yksinkertaisessa, tyylikkäässä komennossa. Kuten ForEach-menetelmä, Kaikki tällä menetelmällä tuotetut objektit palautetaan yleisessä tyyppijärjestelmän kokoelmassa.Kokoelma.Objektimalli.Keräys1.

tästä menetelmästä on olemassa vain yksi versio, jota voidaan kuvata seuraavasti:

Where(scriptblock expression])

hakasulkeiden osoittamalla tavalla lausekesarjalohko on pakollinen ja moodilukujärjestys ja numberToReturn integer-argumentti ovat valinnaisia, joten voit vedota tähän menetelmään käyttämällä 1, 2 tai 3 argumenttia. Jos haluat käyttää tiettyä argumenttia, sinun on annettava kaikki argumentin vasemmalla puolella olevat argumentit (eli jos haluat antaa arvon numbertoreturnaukselle, sinun on annettava arvot myös moodille ja lausekkeelle).

missä(scriptblock-lauseke)

missä-menetelmän alkeellisin kutsumus yksinkertaisesti ottaa script block-lausekkeen argumentiksi. Script block-lauseke arvioidaan kerran jokaista käsiteltävän kokoelman objektia kohti, ja jos se palauttaa true, objekti palautetaan Where-menetelmällä. Tämä on funktionaalinen vastine sille, että kutsutaan missä-objekti cmdletiksi ja siirretään se komentosarjalohkoksi. Kuten missä-objekti cmdlet, $ _ ja $PSItem-muuttujia voidaan käyttää viittaamaan nykyiseen kohteeseen, jota käsitellään komentosarjalohkon sisällä.

tässä on hyvin yksinkertainen esimerkki, joka näyttää, miten voit saada listan käynnissä olevista palveluista.

# Get all services$services = Get-Service# Now filter out any services that are not running$services.where{$_.Status -eq 'Running'}

Tämä ei tarjoa mitään uutta toiminnallisuutta, mutta se tarjoaa paljon nopeamman suorituskyvyn kuin missä-objekti ja syntaksi on melko helppo seurata, joten kannattaa todella harkita tätä skriptejä varten, kun suoritat asiakaspuolen suodatusta kokoelmista, jotka olet tallentanut muuttujaan.

missä(scriptblock-lauseke, WhereOperatorSelectionMode mode)

kun alkaa tarkastella Where-menetelmän valinnaisia parametreja, asiat alkavat muuttua paljon kiinnostavammiksi. Windows PowerShell versio 4.0 sisälsi uuden luettelon, jossa oli järjestelmän nimi.Hallinta.Automaatio.Whereoperators selectionmode. Huomaa tämän tyypin loppuliite: ”SelectionMode”. Sitä käytetään tarjoamaan tehokkaita valintaominaisuuksia missä syntaksi. Tässä ovat tähän luetteloon sisältyvät arvot sekä niiden määritelmät:

Default Filter the collection using the expression script block, to the maximum count if one was provided or defauling to all objects in keräys, jos enimmäislukumäärää ei ole annettu lukumääränä.
ensimmäinen Palauta ensimmäiset n-objektit, jotka läpäisevät lausekesarjauksen lohkosuodattimen, oletusarvon ollessa vain 1 objekti, jos tiettyä lukua ei pyydetty numerosuorituksessa.
Last Palauta viimeiset n-objektit, jotka läpäisevät lausekkeen komentosarjalohkosuodattimen, oletusarvon ollessa vain 1 objekti, jos tiettyä lukua ei pyydetty numerolaskennassa.
SkipUntil Ohita kokoelmassa olevat objektit, kunnes objekti läpäisee lausekkeen komentosarjalohkosuodattimen, ja palauta sitten ensimmäiset n-objektit, oletuksena kaikki jäljellä olevat objektit, jos lukumäärälaskennassa ei annettu enimmäislukua.
kunnes Palauta kokoelman ensimmäiset n-objektit, kunnes objekti läpäisee lausekkeen komentosarjalohkosuodattimen, oletuksena kaikki objektit, jotka johtavat ensimmäiseen ohitettuun objektiin, jos lukumäärälaskennassa ei annettu enimmäislukua.
Split kokoelma.

jokainen näistä tarjoaa jonkin verran ainutlaatuista arvoa, kun käsittelet tiedonkeruita, joten kerron tarkemmin jokaisesta valintatilasta alla.

oletus

ei ole yllättävää, että moodiargumentin oletusarvo on ”Default”. Oletusvalintatila tarjoaa samat toiminnot, jotka saat, kun et tarjoa valintatilaa lainkaan. Olisimme esimerkiksi voineet kirjoittaa edellisen esimerkkimme viimeisen rivin näin:

# Now filter out any services that are not running$services.where({$_.Status -eq 'Running'},'Default')

kyseisessä esimerkissä ylimääräinen argumentti ei kuitenkaan ole välttämätön, koska se tekee täsmälleen saman asian kuin se tekisi, jos et olisi esittänyt argumenttia. Voit myös antaa palautettavien objektien enimmäismäärän, kun käytät Oletusvalintatilaa, käyttäen numeroreturn-argumenttia, kuten tämä:

# Get the first 10 services in our collection that are running$services.where({$_.Status -eq 'Running'},'Default',10)

on tärkeää huomata, että tarkka toiminnallisuus on käytettävissä myös käytettäessä ensimmäistä valintatilaa (josta puhumme hetken kuluttua), joten ei ole käytännöllistä käyttää mitään valinnaisista parametreista lainkaan, kun käytät Oletusvalintatilaa.

ensimmäinen

kuten arvata saattoi, ensimmäisessä valintatilassa voi valita kokoelman ensimmäiset objektit, jotka läpäisevät komentosarjalohko-lausekesuodattimen. Kun käytät ensin ilman arvoa numberToReturn-argumentille tai kun käytät ensin arvoa 0 numberToReturn-argumentille, vain ensimmäinen objekti, joka läpäisee suodattimen, palautetaan. Voit valinnaisesti määrittää, kuinka monta objektia palaa numeroreturn-argumentissa, jolloin monta objektia palautetaan (olettaen, että on niin monta objektia, jotka läpäisevät suodattimen).

Tässä muutamia esimerkkejä palvelukokoelmastamme, joka näyttää ensimmäisen valintatilan toiminnassa:

# Get the first service in our collection that is running$services.where({$_.Status -eq 'Running'},'First')# Get the first service in our collection that is running$services.where({$_.Status -eq 'Running'},'First',1)# Get the first 10 services in our collection that are running$services.where({$_.Status -eq 'Running'},'First',10)

huomaa, että näissä esimerkeissä toinen komento palauttaa samat tulokset kuin ensimmäinen komento, koska se yksinkertaisesti eksplisiittisesti siirtää numeroreturn-argumentin oletusarvon ensimmäistä valintatilaa käytettäessä.

viimeinen

viimeinen valintatila toimii paljolti ensimmäisen valintatilan tavoin, jolloin voi valita kokoelman viimeiset objektit, jotka läpäisevät komentosarjalohko-lausekesuodattimen. Kun käytät Last ilman arvoa numberToReturn-argumentille tai kun käytät Last arvoa 0 numberToReturn-argumentille, vain viimeinen objekti, joka kulkee suodattimen läpi, palautetaan. Voit valinnaisesti määrittää, kuinka monta objektia palaa numeroreturn-argumentissa, jolloin monta objektia palautetaan (olettaen, että on niin monta objektia, jotka läpäisevät suodattimen).

Tässä muutamia esimerkkejä palvelukokoelmastamme, joka näyttää viimeisen valintatilan toiminnassa:

# Get the last service in our collection that is running$services.where({$_.Status -eq 'Running'},'Last')# Get the last service in our collection that is running$services.where({$_.Status -eq 'Running'},'Last',1)# Get the last 10 services in our collection that are running$services.where({$_.Status -eq 'Running'},'Last',10)

myös ensimmäisen valintatilan esimerkkien tavoin näiden esimerkkien toinen komento palauttaa samat tulokset kuin ensimmäinen komento, koska se yksinkertaisesti eksplisiittisesti siirtää numerotiedon argumentin oletusarvon, kun viimeistä valintatilaa käytetään.

SkipUntil

SkipUntil-valintatilassa voit ohittaa kaikki kokoelman objektit, kunnes löydät yhden, joka läpäisee komentosarjalohko-lausekesuodattimen. Kun löydät objektin, joka läpäisee suodattimen, SkipUntil-tila joko palauttaa kaikki kokoelmassa jäljellä olevat objektit, jos numeroreturn-argumentille ei annettu arvoa tai arvo 0, tai palauttaa ensimmäiset n jäljellä olevat objektit kokoelmassa, jos numeroreturn-argumentille annettiin arvoa nolla suurempi. Molemmissa tapauksissa tulokset sisältävät ensimmäisen objektin, joka on läpäissyt suodattimen.

Tässä muutamia esimerkkejä palvelukokoelmamme osajoukon käyttämisestä SkipUntil-valintatilan näyttämiseksi toiminnassa:

# Get a collection of services whose name starts with "c"$services = Get-Service c*# Skip all services until we find one with a status of "Running"$services.where({$_.Status -eq 'Running'},'SkipUntil')# Skip all services until we find one with a status of "Running", then# return the first 2$services.where({$_.Status -eq 'Running'},'SkipUntil',2)

, kunnes

Until-valintatila tarjoaa skipuntil-valintatilan päinvastaisen toiminnallisuuden. Sen avulla voit palauttaa esineitä kokoelma, kunnes löydät yhden, joka kulkee script block lauseke suodatin. Kun löydät objektin, joka läpäisee suodattimen, missä menetelmä lopettaa objektien käsittelyn. Jos et anna arvoa numberToReturn-argumentille tai jos annat arvon 0, Until selection-tila palauttaa kaikki kokoelman objektit, jotka johtavat ensimmäiseen, joka läpäisee komentosarjan Block expression-suodattimen. Jos annat arvon numberToReturn-argumentille, joka on suurempi kuin 0, Until selection-tila palauttaa korkeintaan kyseisen määrän objekteja, mikä tarkoittaa, että se ei välttämättä edes löydä objektia, joka kulkee komentosarjan Block expression-suodattimen läpi.

Tässä muutamia esimerkkejä palvelukokoelmamme eri osajoukosta, jossa näytetään Until selection mode in action:

# Get a collection of services whose name starts with "p"$services = Get-Service p*# Return all services until we find one with a status of "Stopped"$services.where({$_.Status -eq 'Stopped'},'Until')# Return the first 2 services unless we find one with a status of# "Stopped" first$services.where({$_.Status -eq 'Stopped'},'Until',2)

Split

Split selection mode on uniikki. Sen sijaan, että palauttaisit uuden kokoelman, jolla aloitat, se palauttaa uuden kokoelman, joka sisältää sisäisesti kaksi erillistä kokoelmaa. Mitä nämä sisäkkäiset kokoelmat sisältävät, riippuu siitä, miten käytät jaettua valintatilaa. Split voit jakaa kokoelma esineitä kahteen. Oletusarvoisesti, jos et anna arvoa numberToReturn-argumentille tai jos annat arvon 0 numeroreturn-argumentille, Split sijoittaa kaikki objektit, jotka siirtävät script block expression-suodattimen ensimmäiseen sisäkkäiseen kokoelmaan, ja kaikki muut objektit (ne, jotka eivät läpäise script block expression-suodatinta) toiseen sisäkkäiseen kokoelmaan. Jos annat arvon, joka on suurempi kuin 0 numberToReturn-argumentille, split rajoittaa ensimmäisen kokoelman koon kyseiseen enimmäismäärään, ja kaikki jäljellä olevat kokoelman objektit, jopa ne, jotka vastaavat script block expression-suodatinta, sijoitetaan toiseen kokoelmaan.

Tässä muutamia esimerkkejä siitä, miten jaettua valintatilaa voidaan käyttää objektikokoelman jakamiseen eri tavoin:

# Get all services$services = Get-Service# Split the services into two groups: Running and not Running$running,$notRunning = $services.Where({$_.Status -eq 'Running'},'Split')# Show the Running services$running# Show the services that are not Running$notRunning# Split the services into the same two groups, but limit the Running group# to a maximum of 10 items$10running,$others = $services.Where({$_.Status -eq 'Running'},'Split',10)# Show the first 10 Running services$10running# Show all other services$others

kuten tästä esimerkistä näkyy, Split on varsin tehokas valintatila, joka tarjoaa suodatuksen, ryhmittelyn ja valinnan sekoituksen yhdessä komentokutsussa.

tämä valintatilojen kokoelma tekee missä-menetelmästä nopean ja elegantin mutta samalla tehokkaamman kuin missä-objekti, ryhmä-objekti ja valitse-objekti yhdessä putkessa. Mitä siinä ei olisi rakastettavaa?

puutteita Foreachissa ja missä skriptimenetelmät TypePx: ssä

kuten aiemmin tässä artikkelissa mainitsin, olen kirjoittanut type extensions for PowerShell 3: lle.0 ja myöhemmin ja pakattu ne moduuliin nimeltä TypePx. TypePx on komentosarjamoduuli, joka kirjoitettiin kokonaan Powershellissa ja se toimii PowerShell 3.0: ssa tai uudemmassa. Jos käytät PowerShell 3.0: aa (ja vain jos käytät PowerShell 3.0: aa), TypePx määrittelee Foreachin ja missä komentosarjamenetelmät, jotka jäljittelevät Foreachin käyttäytymistä ja missä menetelmät PowerShell 4.0: ssa ja uudemmissa. Vaikka laajennetun tyyppijärjestelmän avulla Powershellissa on mahdollista jäljitellä tätä käyttäytymistä, on muutamia puutteita, jotka johtuvat Powershellissa olevasta toteutuksesta, joka vaikutti siihen, kuinka pitkälle pystyin menemään näiden tyyppilaajennusten kanssa. Tässä osiossa kuvataan joitakin eroja ja rajoituksia, joita on Foreachissa ja joissa skriptimenetelmät TypePx: ssä, joista haluat ehkä olla tietoinen, jos käytät PowerShell 3.0: aa.

Komentosarjalohkot, joihin vedotaan child scope

: ssä ajetusta komentosarjamenetelmästä, toisin kuin Foreachissa ja jossa menetelmät toteutetaan osana PowerShell 4: ää.0 tai uudempi, joka kutsuu lausekkeen komentosarjalohkoa nykyisessä laajuudessa, jossa menetelmää kutsutaan, ForEach ja jossa PowerShell 3.0: ssa toteutetut komentosarjamenetelmät vetoavat lausekkeen komentosarjalohkoon lapsen ulottuvuudessa. Tämä on rajoitus Powershellissa, joka on ollut siellä alusta asti (rajoitus, voisin lisätä, että mielestäni on ylivoimaisesti suurin puute PowerShell kielenä).

tämän rajoituksen vuoksi kaikki muuttujat, jotka määrität lausekkeen komentosarjalohkon sisällä, muuttuvat vain lapsialueessa. Tämä vaikuttaa, jos expression script lohko on tarkoitus päivittää muuttujan soveltamisala, jossa vedotaan ForEach tai missä. On epätodennäköistä, että tämä aiheuttaisi ongelman käytettäessä Where, koska muuttujien muokkaaminen Where expression script-lohkossa ei ole kovin yleistä, mutta ForEach script-lohkoissa tämä voi aiheuttaa ongelman, joten sinun on pidettävä tämä mielessä, jos käytät näitä laajennuksia.

huomautan, että haluaisin poistaa tämän rajoituksen kokonaan, ja uskon pystyväni siihen, mutta tätä artikkelia kirjoittaessani en ole vielä toteuttanut tähän korjausta.

useimmissa, mutta ei kaikissa kokoelmissa on ForEach ja missä menetelmät

PowerShell 4.0: ssa ja uudemmissa, ForEach ja missä menetelmät ovat maagisesti saatavilla kaikille tyypeille, jotka toteuttavat IEnumerable lukuun ottamatta stringiä, Xmlnodea ja tyyppejä, jotka toteuttavat Idictionaryn. Powershellissa extended type system ei salli laajennusten luomista rajapinnoille, vain tyypeille. Tämä on haaste, jos haluat luoda laaja laajennus kuten ForEach ja missä. Nykyisessä toteutuksessa näiden laajennusten TypePx, TypePx moduuli löytää kaikki tyypit kaikista kokoonpanot ladattu nykyisen sovelluksen toimialueen, ja kaikille ei-yleisille tyypeille, jotka määrittelevät IEnumerable mutta ei IDictionary (lukuun ottamatta merkkijono ja XmlNode), sekä kaikille yleisille tyypeille, jotka määrittelevät IEnumerable mutta ei IDictionary yleisiä kokoelmia PSObject, Object, String, Int32, tai Int64, ForEach ja missä skripti menetelmiä luodaan.

Tämä kattaa suuren määrän tyyppejä, jotka omassa testauksessani ovat riittäneet, mutta saatat törmätä tyyppeihin, joissa haluat käyttää näitä menetelmiä ja niitä ei ole saatavilla. Jos asia on niin, kerro minulle Githubin kautta, niin katson, mitä voin tehdä. Tämä on myös rajoitus, jonka haluaisin poistaa, mutta tarvitsen enemmän aikaa tutkia, miten toteuttaa vastaava toiminnallisuus kootussa kokoonpanossa, jossa voin ehkä määritellä sen enemmän kuin se on määritelty PowerShell 4.0: ssa ja uudemmissa.

PowerShell-skriptit eivät ole yhtä nopeita kuin käännetty koodi

tämä lienee sanomattakin selvää, mutta kun kirjoitat jotain Powershelliin, joka on tulkattu kieli, se ei toimi yhtä nopeasti kuin jos kirjoittaisit vastaavan logiikan C#: n kaltaisella kielellä. Tämä pätee ehdottomasti ForEach ja missä käsikirjoitus menetelmiä, jotka sisäisesti käyttävät ForEach-objekti, missä-objekti, ja pipelining matkia käyttäytymistä natiivi ForEach ja missä menetelmiä. Tässä tapauksessa näiden komentojen etuna on niiden tarjoama tyylikäs syntaksi ja toiminnallisuus sekä mahdollisuus käyttää näitä komentosarjoissa PowerShell 3.0 ja 4.0. Suorituskyky hyötyy Foreachissa ja missä ovat vain PowerShell 4.0: n natiivitoteutuksessa.

PowerShell 3.0 vaatii sulkeet kaikkien menetelmäparametrien ympärille

mainitsin yllä olevissa esimerkeissä, että pystyin kutsumaan menetelmän yhdellä kirjaimellisella komentosarjalohkoparametrilla käärimättä kyseistä kirjaimellista komentosarjalohkoa lisäliitteisiin. Tämä ominaisuus on olemassa vain PowerShell 4: ssä.0 tai myöhemmin johtuen parannuksia, jotka tehtiin jäsennin että julkaisu. PowerShell 3.0: ssa jäsennin ei tue tätä, joten sulkuja tarvitaan aina, jotta ForEach ja missä komentosarjamenetelmät toimivat yhdellä kirjaimellisella komentosarjalohkoparametrilla kyseisessä versiossa.

johtopäätös

kun aloin yrittää matkia Foreachin käyttäytymistä ja missä PowerShell 3.0: n taikamenetelmät, en oikein tajunnut, kuinka paljon toiminnallisuutta ne tarjosivat. Kaivautuminen teknisiä yksityiskohtia näiden menetelmien takana, jotta voisin luoda laajennuksia halusin TypePx auttoi paljastaa kaikki piilotetut ominaisuudet näissä erittäin tehokkaita menetelmiä, ja olen erittäin iloinen voidessani jakaa ne teille tässä artikkelissa. Toivon, että nämä tiedot auttavat sinua hyödyntämään tätä ihanaa uutta ominaisuutta PowerShell-työssäsi, vaikka käytät yhä PowerShell 3.0: aa. Hyvää käsikirjoitusta!