Posted in: Základy PowerShellu

Syntaxe PowerShellu

PowerShell má poměrně jednoduchou a přehlednou základní syntaxi, která je někdy narušena, ale většinově funguje. Základní syntaxí příkazu je:

Sloveso-PodstatnéJméno -parametr hodnota

Příkladem pak může být:

Get-Process -name explorer.exe

Jak jsem již uvedl v základní obecné syntaxi, podstatné jméno nemusí být pouze jedno, ale může jich být více zapsaných jako jedno slovo pomocí Calme zápisu (každé slovo začíná velkým písmenem). Příkladem takového zápisu může být přidání záznamu do DNS:

Add-DnsServerResourceRecordAAAA -Name "host24" -ZoneName "mojedomena.local" 
-AllowUpdateAny -IPv6Address "192.168.1.24" -TimeToLive 01:00:00

Všechna běžně dostupná slovesa (vybrané moduly mohou užívat i další, ale vždy se rozsvítí varování při jejich importu) jsou dostupná následujícím příkazem:

Get-Verb

Úplný seznam uvádím níže:

Verb        Group
----        -----
Add         Common
Clear       Common
Close       Common
Copy        Common
Enter       Common
Exit        Common
Find        Common
Format      Common
Get         Common
Hide        Common
Join        Common
Lock        Common
Move        Common
New         Common
Open        Common
Optimize    Common
Pop         Common
Push        Common
Redo        Common
Remove      Common
Rename      Common
Reset       Common
Resize      Common
Search      Common
Select      Common
Set         Common
Show        Common
Skip        Common
Split       Common
Step        Common
Switch      Common
Undo        Common
Unlock      Common
Watch       Common
Backup      Data
Checkpoint  Data
Compare     Data
Compress    Data
Convert     Data
ConvertFrom Data
ConvertTo   Data
Dismount    Data
Edit        Data
Expand      Data
Export      Data
Group       Data
Import      Data
Initialize  Data
Limit       Data
Merge       Data
Mount       Data
Out         Data
Publish     Data
Restore     Data
Save        Data
Sync        Data
Unpublish   Data
Update      Data
Approve     Lifecycle
Assert      Lifecycle
Complete    Lifecycle
Confirm     Lifecycle
Deny        Lifecycle
Disable     Lifecycle
Enable      Lifecycle
Install     Lifecycle
Invoke      Lifecycle
Register    Lifecycle
Request     Lifecycle
Restart     Lifecycle
Resume      Lifecycle
Start       Lifecycle
Stop        Lifecycle
Submit      Lifecycle
Suspend     Lifecycle
Uninstall   Lifecycle
Unregister  Lifecycle
Wait        Lifecycle
Debug       Diagnostic
Measure     Diagnostic
Ping        Diagnostic
Repair      Diagnostic
Resolve     Diagnostic
Test        Diagnostic
Trace       Diagnostic
Connect     Communications
Disconnect  Communications
Read        Communications
Receive     Communications
Send        Communications
Write       Communications
Block       Security
Grant       Security
Protect     Security
Revoke      Security
Unblock     Security
Unprotect   Security
Use         Other

Sloveso vždy uvádí akci, kterou příkaz provede, proto vím, že příkazy začínající na Get, vždy slouží k nějakému získání dat, hodnot, ale nic nemění. Tato slovesa bychom měli užívat i ve vlastních funkcích a měli bychom se držet zásady, že funkce dělá to, co říká dané sloveso v jejím názvu.

Tato syntaxe je skvělá, protože kód je velmi dobře čitelný i pro úplného začátečníka, nebo člověka, který je daného jazyku neznalý. Její slabinou je zdlouhavost, proto se běžně užívají 2 věci, které zápis zkracují a urychlují:

  • zkratky (aliasy) příkazů
  • zápis pouze malými písmeny

Zápis pouze malými písmeny není žádný problém a mohu jej běžně doporučit užít i ve skriptech (dávkových souborech příkazů). PowerShell se pro interaktivní práci snaží zápis zkrátit tak, aby byl rychlý a efektivní. Aby toho dosáhl, má PowerShell tzv. aliasy, což jsou zkratky jednotlivých příkazů. Krom toho, že PowerShell má vestavěnou sadu Aliasů a každé rozšíření má volitelně sadu Aliasů pro své příkazy, může si uživatel defonovat také další svoje alisy. Seznam dostupných alisů získáme příkazem:

Get-Alias

Aliasy jde pohodlněji hledat pomocí definice (tedy uvedení příkazu, pro který chceme alis), např.:

get-alias -Definition Get-ChildItem

Aliasy mají pro správce systémů ještě jeden význam, snaží se PowerShell příkazy mapovat na CMD nebo BASH příkazy, které správci již dobře znají a běžně využívají. Výše uvedený příklad jsem nevybral náhodnou, pojďme se podívat, jaké jsou alisy pro Get-ChildItem:

get-alias -Definition Get-ChildItem

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Alias           dir -> Get-ChildItem
Alias           gci -> Get-ChildItem
Alias           ls -> Get-ChildItem

Uvedené alisiy dir (pro Windows svět) a ls (pro Linuxový svět) jsou příkazy, které zná každý správce a sám tento příkaz využívám výhradně v podobě aliasu, byť poměrně často sáhnu po alisu gci. Další takový příklad je alias copy, který je zkratkou pro Copy-Item, případně Linuxáci budou preferovat aplias cp. Velmi často jsou užívané také alisy where a select, o kterých má člověk pocit, že jsou samotnými příkazy, protože málo kdy je vidět Whre-Object a Select-Object.

Pajpa – svislítko

Další běžnou součástí syntaxe v PowerShellu pro práci v terminálu i skriptech je pajpa. Pajpa má význam předání výstupu jednoho příkazu (výstupního objektu) jako vstupu do dalšího příkazu. Počet těchto předání, které zapášeme není nikterak omezen, ale pro přehlednost se využívá relativně nízký počet, obvykle jedno až tři. Příklad pak může být:

get-alias | where Source -eq "Microsoft.PowerShell.Utility" | Out-GridView

Výše uvedený příkaz vypíše aliasy příkazů, které jsou součástí modulu PowerShell Utility. Tento výpis se zobrazí v samostatném okně mřížky, která umožňuje prohledávání, filtrování a řazení výstupu.

Zapisování textu

Text, stejně jako ve většině programovacích jazyků, zadáváme v uvozovkách, ovšem v PowerShellu to není tak jednoduché, jak by se mohlo zdát. Když text zapíšeme do uvozovek (jak je známe v češtině), bude se vyhodnocovat dynamický obsah, viz následující příklad:

Write-Host "Dnes je $datum"
Dnes je 10.06.2023

Na proti tomu, když užiji apostrof (jednoduché uvozovky), dynamický obsah se nevyhodnocuje a budu mít vždy text přesně takový, jako jej mám zapsaný, viz níže:

Write-Host 'Dnes je $datum'
Dnes je $datum

Pokud chci, aby součástí textu byly uvozovky, např. nějaká citace, musím takový text uzavřít do jednoduchých uvozovek a bude platit, že dynamický obsah se nevyhodnocuje, protože české uvozovky jsou v tomto případě znakem textu, nikoliv vymezením textového řetěžce.

Proměnná

Nedílnou součástí psaní skriptů je využívání proměnných. Stejně jako ostatní skriptovací jazyky má i PowerShell dynamicky typované proměnné, tedy proměnné mění svůj datový typ v závislosti na svém obsahu. Jméno proměnné začíná vždy $, takže proměnnou s názvem cislo založíme následovně:

$cislo

Do proměnné se přiřazuje jako ve většině jazyků (alespoň těch, které vychází z C) pomocí symbolu rovnítko, hodnotu 2 tedy do proměnné cislo přiřadíme následovně:

$cislo = 2

Otázkou ovšem zůstává, jakého datového typu proměnná cislo je. K tomu, abychom tuto otázku zodpověděli si musíme uvědomit, že PowerShell je objektový jazyk vycházející z .NET, takže jeho objekty mají nějaké vlastnosti a funkce, ke kterým se dostaneme pomocí tečky. Datový typ naší proměnné zjistíme následovně

$cislo.gettype().name

Výsledkem bude typ Int32, tedy celé číslo. Co se stane, když do proměnné cislo zapíšeme hodnotu slovem?

$cislo = "dva"
$cislo.gettype().name
String

Nabízí se tedy otázka, mohu při psaní skriptu nějak zajistit, že v proměnné bude třeba text a nic jiného? Odpověď je ano, protože PowerShell umí na rozdíl od jiných dynamicky typovaných skriptovacích jazyků zafixovat typ proměnné, pomocí uvedení datového typu v hranatých závorkách před proměnnou, dokazuje to následující příklad.

PS C:\Users\petra> [string]$cislo = 2
PS C:\Users\petra> $cislo.gettype().name
String
PS C:\Users\petra> $cislo = "dva"
PS C:\Users\petra> $cislo.gettype().name
String

A co když není automatická konverze mezi dvěma typy možná?

PS C:\Users\petra> [int]$cislo = 2
PS C:\Users\petra> $cislo.gettype().name
Int32
PS C:\Users\petra> [int]$cislo = "2"
PS C:\Users\petra> $cislo.gettype().name
Int32
PS C:\Users\petra> [int]$cislo = "dva"
Cannot convert value "dva" to type "System.Int32". Error: "Vstupní řetězec nemá správný formát."
At line:1 char:1
+ [int]$cislo = "dva"
+ ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : MetadataError: (:) [], ArgumentTransformationMetadataException
    + FullyQualifiedErrorId : RuntimeException

Jak je vidět, PowerShell vyhodí chybu a hodnotu do proměnné nezapíše. Zároveň však např. číslo zapsané číslicí ve formátu textu pozná a převede jej na číslo.

Proměnná Pajpy

Výchozí proměnná, proměnná pajpy či jinými názvy pojmenovávaný proměnná, která obsahuje objekt, jež je předávám mezi příkazy pomocí pajpy. Tato proměnná je součástí vlastního PowerShellu a má dvoje značení (od verze 3)

  • $_ se obvykle značí a pomocí $_.<vlastnost> se dostanu k vlastnostem objektu, který mi přichází z pajpy
  • $PSItem je plný názve pro tuto proměnnou, kterou nejčastěji zapisujeme jako $_

Další informace o proměnných najdete v dokumentaci PowerShellu a budeme se jim postupně věnovat v dalších článcích tak, jak je budeme potřebovat.

Proměnné prostředí Windows

Každý admin ví, že systém Windows má vlastní systémové proměnné. Tyto proměnné jsou v PowerShellu rovněž dostupné, ale jinak, nežli v CMD, nebo dialogu spustit, kde se uzavírají do symbolů procento. V PowerShellu mají zvláštní zápis, kde součástí jména proměnné je env:, viz příklad:

$Env:windir

Objekt

Opravdu velmi zjednodušeně jde říct, že v PowerShellu je objektem vše. Pokud se chci k něčemu chovat jako k objektu, není to nic těžkého.

  • Proměnná rovnou využívá tečkové notace
  • Příkaz zavřu do kulatých závorek a využívám tečkové notace

Přístup k vlastnostem objektu na proměnné jsme tu již viděli, jde o:

$cislo.gettype().name

Tento příklad je malinko zvláštní, protože na objektu proměnné $cislo využíváme metodu a na výstupním objektu této metody pak vlastnost. Jak by to bylo s tím, když chci objektově přistoupit k příkazu?

(Get-Date).AddHours(8)

Výše uvedený příkaz vrátí datum a čas, který bude platný za 8 hodin, přičemž využívá metodu objektu, který je vracen příkazem Get-Date.

Programátoři se ovšem nemusí bát, objekty je možné vytvářet pomocí tříd stejně, jako v jiných objektových jazycích, ale jde již o pokročilou věc, kterou IT profesionálové nejspíš potřebovat nebudou, proto si danou syntaxi najděte v dokumentaci.

Bloky

Již opravdu poslední částí obecné syntaxe jsou bloky, ať jde o funkce, větvení, skriptbloky, či sekce DSC. Všechny bloky uzavíráme do složených závorek, např.

try {New-Item -Path Z:\zaloha -name Dnesek -type "directory"} catch {write-host "Nezdařilo se"}

Back to Top