Az összefűzés és szétdarabolás operátora (‑join, ‑split, ‑csplit)

A PowerShell 2.0 két új operátort hoz be a repertoárjába, mindkettő tulajdonképpen korábban is használatos funkciókat hajt végre talán egy picit egyszerűbben. Az egyik a sztringek összefűzését végrehajtó –join  operátor:

PS C:\> "egy", "kettő", "három" -join "-"

egy-kettő-három

Az operátor bal oldalán áll az összefűzendő szövegek tömbje, jobb oldalán meg az összefűzéskor beillesztett karakter vagy sztring.

Érdekes módon, egyoperandusú operátorként is használhatjuk, de ehhez szerintem egy picit PowerShell-idegen formátumot kell alkalmazni:

PS C:\> -join ("egy", "kettő", "három")

egykettőhárom

Ilyenkor az összefűző karakter egy üres-sztring. Én személy szerint nem igazán javaslom a használatát.

Megjegyzés

Ráadásul itt azért kell a zárójelet használni, mert a PowerShell parancsfeldolgozója az egytagú operátorokat nagyobb precedenciájúnak tekinti, mint a többparaméteres operátorokat (jelen esetben a vessző tömboperátort), így a zárójel nélkül nem igazán jó eredményt kapunk:

[66] PS C:\> -join "egy", "kettő", "három"

egy

kettő

három

Hiszen itt valójában a (-join "egy"), "kettő", "három" kerül végrehajtásra.

A művelet fordítottját, azaz a szétdarabolást a –split  operátor végzi:

PS C:\> "egy-kettő-három" -split "-"

egy

kettő

három

Ráadásul ez regex szemlélettel működik alaphelyzetben, azaz számjegyek mentén való darabolást az alábbi kifejezéssel lehet végrehajtani:

PS C:\> "egy1kettő2három3" -split "\d"

egy

kettő

három

Ha még ez sem lenne elég, akkor $true vagy $false értékre kiértékelődő bármilyen PowerShell kifejezés is írható:

PS C:\> "egy-kettő+három.négy!öt" -split {$_ -eq "-" -or $_ -eq "+"}

egy

kettő

három.négy!öt

Ezt úgy kell értelmezni, mint egy csőfeldolgozást: érkeznek a karakterek a sztringből, és amelyik kielégíti a feltételt, amentén tördel.

A tördelés eredményét be is lehet korlátozni. Ha én csak maximum 3 darabot szeretnék kapni a széttördelés után, akkor a –split-nek még egy szám paramétert adva ezt megtehetem:

PS C:\> '1.2.3.4.5.6.7.8' -split "\.", 3

1

2

3.4.5.6.7.8

(Ugye itt sem felejtkezünk meg a regex szintaxisról, azaz a „.” mentén való tördeléshez a „\.” kifejezést kell használni.)

A tördelés operátorának van néhány beállítható opciója is. Ha az a kifejezés, ami mentén tördelni akarunk egyszerű kifejezés, és esetleg olyan karakterek is vannak benne, amelyek a regexben vezérlő karakterek, akkor használhatjuk a „SimpleMatch” opciót:

[1] PS C:\munka> 'Egy$kettő$három' -split '$',0

Egy$kettő$három

 

[2] PS C:\munka> 'Egy$kettő$három' -split '$',0, "simplematch"

Egy

kettő

három

A fenti első nem működött, hiszen a „$” jel speciális jelentésű a regexben, a második eset már a kívánt eredményt adta. Ha ilyen opciókat használunk, akkor kötelező használni a maximális darabszámot meghatározó paramétert is (0 jelenti az összes darabot), hiszen csak így kerül helyére a „simplematch” opció.

A regex típusú tördelésnél a regex összes opcióját használhatjuk:

[RegexMatch] [,IgnoreCase] [,CultureInvariant] [,IgnorePatternWhitespace] [,ExplicitCapture] [,Singleline | ,Multiline]

 Ráadásul a –split operátornak van egy –csplit  kis-nagybetű érzékeny változata is:

[67] PS C:\> "axb" -csplit "x"

a

b

[68] PS C:\> "aXb" -csplit "x"

aXb

Látható, hogy a fenti példákban a –csplit csak a kisbetűs „x” mentén tördelt.

További trükkök a darabolással

A darabolásnál láttuk, hogy az a karakter(sorozat), ami mentén darabolunk, az nem fog szerepelni az eredmény darabjai között. Például a következő kötőjelek mentén történő darabolás eredményében nincs egy darab kötőjel sem:

[1] PS C:\> "egy-kettő-három" -split "-"

egy

kettő

három

Mi van akkor, ha erre mégis szükség van? Na de pontosan hogyan is szeretnénk megőrizni ezeket a kötőjeleket? Ha külön darabként, akkor nagyon egyszerűen zárójelbe kell tenni ezt a kötőjelet:

[2] PS C:\> "egy-kettő-három" -split "(-)"

egy

-

kettő

-

három

Ha az a cél, hogy az előtte levő darabhoz csatlakozzon a kötőjel, akkor valójában nem maga a kötőjel a törési pont, hanem a kötőjel és az utána következő betű közti pozíció. Ilyenkor tehát ezt a pozíciót kell meghatározni, nem pedig magát a kötőjelet. Ezt előretekintéssel és hátratekintéssel tudjuk megtenni:

[3] PS C:\> "egy-kettő-három" -split "(?<=-)(?=\w)"

egy-

kettő-

három

Ezt a gondolatot folytassuk, vajon hogyan lehet például egy szöveget két karakterenként feldarabolni? Jönne az ötlet, hogy zárójelezzük a két karaktert jelölő tagot:

[4] PS C:\> "abcdef" -split "(\w{2})"

 

ab

 

cd

 

ef

Ez láthatóan nem tökéletes, hiszen ilyenkor az első két karakternél már darabolhatunk, kijön a darab előtti rész, a semmi, majd a zárójelezés miatt a két karakter. Majd folyatódik a folyamat, így az eredményben lesz egy csomó üres szöveg. Persze ki lehetne ezt szűrni, de próbáljuk meg elegánsabban ezt megoldani! Használjuk az előretekintés-hátratekintés kombinációt ismét:

[5] PS C:\> "abcdef" -split "(?<=\w{2})(?=\w)"

ab

c

d

e

f

Nem lett tökéletes. Próbáljunk meg együtt gondolkodni a regexszel! Az ’ab’ után egyértelmű, hogy lehet tördelni, viszont a ’c’ után is lehet, hiszen a ’c’ utáni pozícióban is igaz, hogy volt előtte két karakter. Valahogy rá kellene venni a regexszet, hogy ha egy darabot letört, akkor azt már ne is vegye figyelembe, azaz kezdjen új életet. Szerencsére erre is van lehetőség egy eddig még nem tárgyalt jelölővel, ez a ’\G’. Itt megint csak fontos a nagybetűs G.

[7] PS C:\> "abcdef" -split "(?<=\G\w{2})(?=\w)"

ab

cd

ef

Ez már tökéletes eredményt adott.



Word To HTML Converter