Storicamente, gli strumenti da riga di comando nelle sistemi Unix sono stati sviluppati meglio che in Windows, tuttavia con l'introduzione di una nuova soluzione la situazione è cambiata.
Con PowerShell è possibile scrivere script in un linguaggio interpretato multi-paradigma, che contiene elementi di programmazione procedurale, orientata agli oggetti e persino funzionale: salti condizionali, cicli, variabili, array, hash table, classi, gestione degli errori, oltre a funzioni, cmdlet e pipeline. si dedicava alle basi del lavoro nell'ambiente, e ora proponiamo ai lettori una piccola guida per programmatori.
Indice:
È possibile scrivere codice in qualsiasi editor di testo o utilizzando un ambiente di sviluppo integrato: la soluzione più semplice è utilizzare Windows PowerShell ISE incluso nelle distribuzioni dei sistemi operativi server Microsoft. Questo è necessario solo per script sufficientemente complessi: set di comandi brevi possono essere eseguiti più facilmente in modalità interattiva.
Commenti
L'uso dei commenti è considerato parte di un buon stile di programmazione, insieme a indentazioni e spazi corretti:
# Для строчных комментариев используется символ решетки — содержимое строки интерпретатор не обрабатывает.
<#
Так обозначаются начало и конец блочного комментария.
Заключенный между ними текст интерпретатор игнорирует.
#>
Variabili e loro tipi
Le variabili in PowerShell sono oggetti con nome. I loro nomi possono includere il carattere di sottolineatura, così come lettere e numeri. Davanti al nome si usa sempre il simbolo $, e per dichiarare una variabile, è sufficiente specificare un nome valido all'interprete:

Per inizializzare una variabile (assegnarle un valore) si utilizza l'operatore di assegnazione (simbolo =):
$test = 100Si può dichiarare una variabile specificando il suo tipo tra parentesi quadre (operatore di casting) prima del nome o del valore:
[int]$test = 100
$test = [int]100È importante capire che le variabili in PowerShell sono oggetti completi (classi) con proprietà e metodi i cui tipi si basano su quelli presenti in .NET Core. Elenchiamo i principali:
Tipo (classe .NET)
Descrizione
Esempio di codice
[string]
System.String
stringa Unicode
$test = "test"
$test = 'test'
[char]
System.Char
carattere Unicode (16 bit)
[char]$test = 'c'
[bool]
System.Boolean
tipo booleano (valore logico True o False)
[bool]$test = $true
[int]
System.Int32
numero intero a 32 bit
[int]$test = 123456789
[long]
System.Int64
numero intero a 64 bit
[long]$test = 12345678910
[single]
System.Single
numero in virgola mobile di lunghezza 32 bit
[single]$test = 12345.6789
[double]
System.Double
numero in virgola mobile di lunghezza 64 bit (8 byte)
[double]$test = 123456789.101112
[decimal]
System.Decimal
numero in virgola mobile di lunghezza 128 bit (deve avere d alla fine)
[decimal]$test = 12345.6789d
[DateTime]
System.DateTime
data e ora
$test = Get-Date
[array]
System.Object[]
array, indice degli elementi che inizia da 0
$test_array = 1, 2, "test", 3, 4
[hashtable]
System.Collections.Hashtable
tabelle hash — array associativi con chiavi nominate, costruite secondo il principio: @{chiave = "valore"}
$test_hashtable = @{one="uno"; two="due"; three="tre"}
PowerShell supporta la conversione implicita dei tipi, inoltre il tipo della variabile può cambiare dinamicamente (ad esempio, mediante l'operatore di assegnazione), se non specificato forzatamente — in questo caso l'interprete restituirà un errore. È possibile determinare il tipo di variabile dall'esempio precedente utilizzando il metodo GetType():
$test.GetType().FullName 
Ci sono alcuni cmdlet per gestire le variabili. La loro lista viene visualizzata in un formato comodo tramite il comando:
Get-Command -Noun Variable | ft -Property Name, Definition -AutoSize -Wrap 
Per visualizzare le variabili dichiarate e i loro valori, è possibile utilizzare un cmdlet speciale:
Get-Variable | moreQuesto metodo sembra eccessivamente ingombrante; è molto più comodo lavorare con le variabili attraverso operatori o accedendo direttamente alle loro proprietà e metodi. Tuttavia, i cmdlet hanno la loro utilità, poiché consentono di impostare alcuni parametri aggiuntivi. È importante comprendere che le variabili utente sono definite solo nel contesto della sessione corrente. Dopo la chiusura della console o il completamento dello script, vengono eliminate.
Variabili di sistema
Oltre alle variabili dichiarate dall'utente, esistono variabili incorporate (di sistema) che non vengono eliminate al termine della sessione corrente. Si dividono in due tipi, e i dati di stato di PowerShell sono conservati in variabili automatiche, a cui non è possibile assegnare valori arbitrari. Tra queste c'è ad esempio $PWD:
$PWD.Path 
Per memorizzare le impostazioni personalizzate, ci sono variabili di preferenza, i cui valori possono essere modificati. Ad esempio, con $ErrorActionPreference si definisce come l'interprete dei comandi deve reagire in caso di errori non critici.
In aggiunta agli operatori e ai cmdlet per accedere alle variabili dichiarate, esiste un pseudo-archivio chiamato Variable:. Si può lavorare con esso seguendo il medesimo principio degli altri archivii, e le variabili in questo caso somigliano a oggetti nel file system:
Get-ChildItem Variable: | moreo
ls Variable: | more 
Ambiti di visibilità
Per le variabili in PowerShell esiste il concetto di ambito (Scope). L'ambito globale (Global) si estende a tutta la sessione corrente — comprende, ad esempio, le variabili di sistema. Le variabili locali (Local) sono disponibili solo nell'ambito in cui sono state definite: ad esempio, all'interno di una funzione. C'è anche il concetto di ambito dello script (Script), ma per i comandi di script è essenzialmente locale. Per impostazione predefinita, quando si dichiarano le variabili, viene assegnato un ambito locale, e per modificarlo è necessaria una costruzione speciale del tipo: $Global: variabile = valore.
Ad esempio, in questo modo:
$Global:test = 100
Variabili d'ambiente
Da PowerShell è disponibile un altro pseudo-repository Env:, che consente di accedere alle variabili di ambiente. Al momento dell'avvio della shell, esse vengono copiate dal processo padre (cioè dal programma che ha avviato la sessione corrente) e i loro valori iniziali coincidono generalmente con quelli del pannello di controllo. Per visualizzare le variabili di ambiente, si utilizza il cmdlet Get-ChildItem o i suoi alias: ls e dir.
dir Env: 
Queste variabili rappresentano sequenze di byte (o caratteri, se preferite), la cui interpretazione dipende esclusivamente dal programma che le utilizza. I cmdlet *-Variable non funzionano con le variabili di ambiente. Per accedervi, è necessario utilizzare il prefisso del disco:
$env:TEST = "Hello, World!" 
Operatori aritmetici e operatori di confronto
In PowerShell ci sono i seguenti operatori aritmetici: + (addizione), — (sottrazione), * (moltiplicazione), / (divisione) e % (modulo o resto della divisione). Il risultato di un'espressione aritmetica viene calcolato da sinistra a destra secondo l'ordine delle operazioni. Le parentesi tonde vengono utilizzate per raggruppare le parti dell'espressione. Gli spazi tra gli operatori vengono ignorati e servono solo per facilitare la lettura. L'operatore + unisce, mentre l'operatore * ripete le stringhe. Quando si cerca di sommare un numero a una stringa, esso verrà convertito in stringa. Inoltre, PowerShell offre numerosi operatori di confronto che verificano la corrispondenza tra due valori e restituiscono valori booleani True o False:
L'operatore
Descrizione
Esempio di codice
-eq
Uguale / Rappresenta (equivalente a = o == in altri linguaggi)
$test = 100
$test -eq 123
-ne
Diverso / Non uguale (equivalente a <> o !=)
$test = 100
$test -ne 123
-gt
Maggiore di / Maggiore (equivalente a >)
$test = 100
$test -gt 123
-ge
Maggiore o uguale / Maggiore o uguale (equivalente a >=)
$test = 100
$test -ge 123
-lt
Minore di / Minore (equivalente a <)
$test = 100
$test -lt 123
-le
Minore o uguale / Minore o uguale (equivalente a <=)
$test = 100
$test -le 123
Esistono anche altri operatori simili che consentono, ad esempio, di confrontare le stringhe tenendo conto dei caratteri jolly o di utilizzare espressioni regolari per cercare corrispondenze con un modello. Li esamineremo in dettaglio nei prossimi articoli. I simboli e = non sono utilizzati per i confronti, poiché sono impiegati per altri scopi.
Operatori di assegnazione
Oltre all'operatore più comune =, ci sono altri operatori di assegnazione: +=, -=, *=, /= e %= che modificano il valore prima dell'assegnazione. Gli operatori unari ++ e -- si comportano in modo simile, incrementando o diminuendo il valore della variabile, e anche loro sono considerati operatori di assegnazione.
Operatori logici
Per descrivere condizioni complesse, non basta solo il confronto. È possibile scrivere espressioni logiche utilizzando operatori come: -and, -or, -xor, -not e!.. Funzionano come in altri linguaggi di programmazione, con la possibilità di utilizzare le parentesi tonde per definire l'ordine di valutazione:
("Test" -eq "Test") -and (100 -eq 100)
-not (123 -gt 321)
!(123 -gt 321)
Salto condizionale
Gli operatori di branching in PowerShell sono standard: IF(IF…ELSE, IF…ELSEIF…ELSE) e SWITCH. Esamineremo il loro utilizzo tramite esempi:
[int]$test = 100
if ($test -eq 100) {
Write-Host "test = 100"
}
[int]$test = 50
if ($test -eq 100) {
Write-Host "test = 100"
}
else {
Write-Host "test 100"
}
[int]$test = 10
if ($test -eq 100) {
Write-Host "test = 100"
}
elseif ($test -gt 100) {
Write-Host "test > 100"
}
else {
Write-Host "test 5 o valore non definito"}
}
Cicli
In PowerShell ci sono diversi tipi di cicli: WHILE, DO WHILE, DO UNTIL, FOR e FOREACH.
Il ciclo con condizione iniziale funziona se/finché è vero:
[int]$test = 0
while ($test -lt 10) {
Write-Host $test
$test = $test + 1
}
I cicli con condizione finale verranno eseguiti almeno una volta, poiché la verifica della condizione viene effettuata dopo l'iterazione. In questo caso, DO WHILE funziona finché la condizione è vera, mentre DO UNTIL funziona finché è falsa:
[int]$test = 0
do {
Write-Host $test
$test = $test + 1
}
while ($test -lt 10)
[int]$test = 0
do {
Write-Host $test
$test = $test + 1
}
until ($test -gt 9)
Il numero di iterazioni del ciclo FOR è noto in anticipo:
for ([int]$test = 0; $test -lt 10; $test++) {
Write-Host $test
}
Nel ciclo FOREACH si esegue il passaggio degli elementi di un array o di una collezione (tabelle hash):
$test_collection = "item1", "item2", "item3"
foreach ($item in $test_collection)
{
Write-Host $item
}
Array
In PowerShell, variables can store not only single objects (such as numbers or strings) but also multiple ones. The simplest type of these variables is arrays. An array can consist of several elements, one element, or be empty, meaning it contains no elements. To declare it, we use the @() operator, which will be essential in the next article — it's crucial for adding other arrays to an array (creating multidimensional arrays), passing arrays as arguments to functions, and similar tasks.
$test_array = @() #create an empty arrayWhen initializing an array, its values are separated by commas (the special operator ,):
$test_array = @(1, 2, 3, 4) # create an array of four elements In most cases, the @() operator can be omitted:
$test_array = 1, 2, 3, 4In this case, an array with a single element is initialized as follows
$test_array = , 1To access elements of an array, a zero-based integer index is used along with the index operator (square brackets):
$test_array[0] = 1Multiple indices can be specified using commas, including repeated ones:
$test_array = "uno", "due", "tre", "quattro"
$test_array[0,1,2,3]
$test_array[1,1,3,3,0] 
L'operatore .. (due punti — operatore di intervallo) restituisce un array di numeri interi in un determinato intervallo superiore e inferiore. Ad esempio, l'espressione 1..4 produce un array di quattro elementi @(1, 2, 3, 4), mentre l'espressione 8..5 produce @(8, 7, 6, 5).

Utilizzando l'operatore di intervallo, è possibile inizializzare un array ($test_array = 1..4) oppure ottenere uno slice, cioè una sequenza di elementi di un array con indici da un altro. Qui, il numero negativo -1 rappresenta l'ultimo elemento dell'array, -2 rappresenta il penultimo e così via.
$test_array = "uno", "due", "tre", "quattro"
$test_array[0..2]
$test_array[2..0]
$test_array[-1..0]
$test_array[-2..1]Si prega di notare che i valori di un array di interi possono essere maggiori del valore massimo dell'indice dell'array con i dati. In questo caso, vengono restituiti tutti i valori fino all'ultimo:
$test_array[0..100]Se si tenta di accedere a un singolo elemento non esistente dell'array, viene restituito il valore $null.

In PowerShell, gli array possono contenere elementi di diversi tipi o essere fortemente tipizzati:
$test_array = 1, 2, "test", 3, 4
for ([int]$i = 0; $i -lt $test_array.count; $i++)
{
Write-Host $test_array[$i]
}
Dove la proprietà $test_array.count rappresenta il numero di elementi nell'array.
Esempio di creazione di un array fortemente tipizzato:
[int[]]$test_array = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
Hash table
Un altro tipo di variabili base nel linguaggio PowerShell è le hash table, comunemente chiamate array associative. Le Hashtable sono simili agli oggetti JSON e sono costruite secondo il principio chiave-valore. A differenza dei normali array, l'accesso ai loro elementi avviene tramite chiavi nominate, che sono proprietà dell'oggetto (è possibile anche usare l'operatore di indicizzazione — le parentesi quadre).
Una hash table vuota è dichiarata utilizzando il simbolo di controllo @ e le parentesi operative:
$test_hashtable = @{}Al momento della dichiarazione, è possibile creare immediatamente le chiavi e assegnare i loro valori:
$test_hashtable = @{one="uno"; two="due"; three="tre"; "some key"="some value"}Per aggiungere un elemento alla hash table, bisogna assegnare una chiave non esistente o utilizzare il metodo Add(). Se l'assegnazione avviene con una chiave esistente, il suo valore verrà modificato. Per rimuovere un elemento dalla hash table si usa il metodo Remove().
$test_hashtable."some key"
$test_hashtable["some key"]
$test_hashtable.Add("four", "quattro")
$test_hashtable.five = "cinque"
$test_hashtable['five'] = "sostituisci valore"
$test_hashtable.Remove("one") 
Le variabili di questo tipo possono essere passate come argomenti a funzioni e cmdlet: nell'articolo successivo vedremo come fare e parleremo anche di un altro tipo simile: PSCustomObject.
Le funzioni
Nel linguaggio PowerShell ci sono tutti gli elementi necessari per la programmazione procedurale, comprese le funzioni. Per definirle si utilizza la parola chiave Function, seguita dal nome della funzione e dal corpo racchiuso tra parentesi tonde. Se è necessario passare argomenti alla funzione, possono essere specificati subito dopo il nome, tra parentesi.
function nome-funzione (argomento1, ..., argomentoN)
{
corpo-funzione
}
La funzione restituisce sempre un risultato: si tratta di un array dei risultati di tutte le sue dichiarazioni, se ce ne sono più di una. Se c'è solo una dichiarazione, viene restituito un unico valore del tipo corrispondente. La costruzione return $value aggiunge un elemento con il valore $value all'array dei risultati e interrompe l'esecuzione dell'elenco delle dichiarazioni, mentre una funzione vuota restituisce $null.
Per esempio, creiamo una funzione per elevare un numero al quadrato:
function sqr ($number)
{
return $number * $number
}
Va notato che nel corpo della funzione puoi utilizzare tutte le variabili dichiarate prima della sua chiamata, e la chiamata delle funzioni in PowerShell può sembrare insolita: gli argomenti (se presenti) non sono racchiusi tra parentesi e sono separati da spazi.
sqr 2oppure così:
sqr -number 2A causa del modo in cui vengono passati gli argomenti, a volte è necessario racchiudere la funzione tra parentesi:
function test_func ($n) {}
test_func -eq $null # la funzione non è stata chiamata
(test_func) -eq $null # il risultato dell'espressione è $true 
Quando descrivi una funzione, puoi assegnare ai parametri dei valori predefiniti:
function func ($arg = value) {
#corpo della funzione
}
Esiste un'altra sintassi per descrivere gli argomenti della funzione, inoltre i parametri possono essere letti dal pipeline: tutto ciò sarà utile nel prossimo articolo, quando tratteremo dei moduli esportabili e della creazione di propri cmdlet.
Gestione degli errori
In PowerShell, there is a mechanism called Try…Catch…Finally that enables handling exceptional situations. The Try block contains code where an error may occur, while the Catch block is its handler. If there was no error, it will not execute. The Finally block runs after the Try block regardless of whether an error occurred, and there can be multiple Catch blocks for different types of exceptions. The exception itself is assigned to a variable that does not require declaration by default ($_) and can be easily extracted. In the example below, we implement protection against incorrect input values:
try {
[int]$test = Read-Host "Inserisci un numero"
100 / $test
} catch {
Write-Warning "Numero non valido"
Write-Host $_
}

Con questo, concludiamo la revisione delle basi della programmazione in PowerShell. Negli articoli successivi, esamineremo in modo più approfondito il lavoro con variabili di diversi tipi, collezioni, espressioni regolari, creazione di funzioni, moduli e comandi personalizzati, così come la programmazione orientata agli oggetti.
Fonte: habr.com
