Historicamente, as utilidades de linha de comando em sistemas Unix foram melhor desenvolvidas do que em Windows, mas com o surgimento dessa nova solução, a situação mudou.
Para o PowerShell, é possível escrever scripts em uma linguagem interpretada multiparadigma, que contém elementos de programação procedural clássica, orientada a objetos e até funcional: desvio condicional, loops, variáveis, arrays, tabelas hash, classes, manipulação de erros, assim como funções, cmdlets e pipelines. foi dedicado aos fundamentos do trabalho no ambiente, e agora oferecemos aos leitores um pequeno guia para programadores.
Conteúdo:
É possível escrever código em qualquer editor de texto ou utilizando um ambiente integrado de desenvolvimento — a forma mais simples é usar o Windows PowerShell ISE, disponível nas edições do sistema operacional servidor da Microsoft. Isso é necessário apenas para scripts mais complexos: conjuntos curtos de comandos são mais fáceis de executar em modo interativo.
Comentários
O uso de comentários é considerado parte de um bom estilo de programação, assim como indentação e espaçamentos corretos:
# Для строчных комментариев используется символ решетки — содержимое строки интерпретатор не обрабатывает.
<#
Так обозначаются начало и конец блочного комментария.
Заключенный между ними текст интерпретатор игнорирует.
#>
Variáveis e seus tipos
As variáveis no PowerShell são objetos nomeados. Seus nomes podem incluir underscore, letras e números. Sempre se usa o símbolo $, e para declarar uma variável, é suficiente informar ao interpretador um nome válido:

Para inicializar uma variável (atribuir-lhe um valor), usamos o operador de atribuição (símbolo =):
$test = 100Uma variável pode ser declarada especificando seu tipo entre colchetes (operador de conversão de tipo) antes do nome ou valor:
[int]$test = 100
$test = [int]100É importante entender que as variáveis no PowerShell são objetos completos (classes) com propriedades e métodos, cujos tipos se baseiam no que existe no .NET Core. Vamos listar os principais:
Tipo (classe .NET)
Descrição
Exemplo de código
[string]
System.String
string Unicode
$test = "teste"
$test = 'teste'
[char]
System.Char
símbolo Unicode (16 bits)
[char]$test = 'c'
[bool]
System.Boolean
tipo booleano (valor lógico True ou False)
[bool]$test = $true
[int]
System.Int32
número inteiro de trinta e dois bits (32 bits)
[int]$test = 123456789
[long]
System.Int64
número inteiro de sessenta e quatro bits (64 bits)
[long]$test = 12345678910
[single]
System.Single
número de ponto flutuante de 32 bits
[single]$test = 12345.6789
[double]
System.Double
número de ponto flutuante de 64 bits (8 bytes)
[double]$test = 123456789.101112
[decimal]
System.Decimal
número de ponto flutuante de 128 bits (deve incluir d no final)
[decimal]$test = 12345.6789d
[DateTime]
System.DateTime
data e hora
$test = Get-Date
[array]
System.Object[]
array, índice de elementos começando em 0
$test_array = 1, 2, "teste", 3, 4
[hashtable]
System.Collections.Hashtable
tables hash — arrays associativos com chaves nomeadas, construídos no princípio: @{chave = "valor"}
$test_hashtable = @{one="um"; two="dois"; three="três"}
O PowerShell suporta conversão implícita de tipos além de permitir que o tipo da variável mude durante a execução (por exemplo, usando o operador de atribuição), se não for especificado forçosamente — neste caso, o interpretador retornará um erro. O tipo da variável no exemplo anterior pode ser determinado usando o método GetType():
$test.GetType().FullName 
Há um número de cmdlets para gerenciar variáveis. Sua lista pode ser exibida de forma conveniente usando o comando:
Get-Command -Noun Variable | ft -Property Name, Definition -AutoSize -Wrap 
Para visualizar as variáveis declaradas e seus valores, pode-se usar um cmdlet especial:
Get-Variable | moreEsse método pode parecer excessivamente verboso, e trabalhar com variáveis é mais conveniente através de operadores ou acessando suas propriedades e métodos diretamente. No entanto, os cmdlets têm seu valor, pois permitem definir alguns parâmetros adicionais. É importante entender que variáveis de usuário são definidas apenas no contexto da sessão atual. Após fechar o console ou terminar o script, elas são removidas.
Variáveis do sistema
Além das variáveis declaradas pelo usuário, existem variáveis internas (sistêmicas) que não são removidas após o término da sessão atual. Elas se dividem em dois tipos, sendo que dados sobre o estado do PowerShell são mantidos em variáveis automáticas, que não podem ser atribuídas manualmente a valores arbitrários. Um exemplo disso é o $PWD:
$PWD.Path 
Para armazenar as preferências do usuário, são necessárias variáveis de preferência, cujos valores podem ser alterados. Por exemplo, com o $ErrorActionPreference, é possível definir como o interpretador de comandos deve reagir a erros não críticos.
Além dos operadores e cmdlets para acessar as variáveis declaradas, existe um pseudo-arquivo chamado Variable:. Você pode trabalhar com ele de maneira semelhante a outros arquivos, e as variáveis, nesse caso, se assemelham a objetos do sistema de arquivos:
Get-ChildItem Variable: | moreou
ls Variable: | more 
Escopos
Para as variáveis no PowerShell, existe o conceito de escopo (Scope). A ação do escopo global (Global) se estende a toda a sessão atual — inclui, por exemplo, variáveis do sistema. Variáveis locais (Local) estão disponíveis apenas no escopo onde foram definidas: digamos, dentro de uma função. Existe também o conceito de escopo de script (Script), mas para os comandos de script, ele é essencialmente local. Por padrão, ao declarar variáveis, elas recebem um escopo local, e para mudar isso, é necessária uma construção especial, como: $Global: variável = valor.
Por exemplo, assim:
$Global:test = 100
Variáveis de ambiente
No PowerShell, há também um pseudo-arquivo chamado Env:, que permite acessar as variáveis de ambiente. Ao iniciar o shell, elas são copiadas do processo pai (ou seja, da aplicação que iniciou a sessão atual) e, geralmente, seus valores iniciais coincidem com os valores do painel de controle. Para visualizar as variáveis de ambiente, utiliza-se o cmdlet Get-ChildItem ou seus pseudônimos (alias): ls e dir.
dir Env: 
Essas variáveis são sequências de bytes (ou caracteres, se preferir), cuja interpretação depende apenas do programa que as utiliza. Cmdlets *-Variable não funcionam com variáveis de ambiente. Para acessá-las, é necessário usar o prefixo do disco:
$env:TEST = "Hello, World!" 
Operadores aritméticos e operadores de comparação
No PowerShell, existem os seguintes operadores aritméticos: + (adição), — (subtração), * (multiplicação), / (divisão) e % (módulo ou resto da divisão). O resultado da expressão aritmética é calculado da esquerda para a direita de acordo com a ordem de operações padrão, e parênteses são usados para agrupar partes da expressão. Os espaços entre os operadores são ignorados, sendo usados apenas para facilitar a leitura. O operador + também concatena, e o operador * repete strings. Ao tentar adicionar um número a uma string, este será convertido em string. Além disso, a linguagem PowerShell possui vários operadores de comparação que verificam a correspondência entre dois valores e retornam booleanos True ou False:
Operador
Descrição
Exemplo de código
-eq
Igual / Equivale (análogo a = ou == em outras linguagens)
$test = 100
$teste -eq 123
-ne
Diferente / Não igual (análogo a ou !=)
$test = 100
$teste -ne 123
-gt
Maior que / Superior a (análogo a >)
$test = 100
$teste -gt 123
-ge
Maior ou igual a / Superior ou igual a (análogo a >=)
$test = 100
$teste -ge 123
-lt
Menor que / Inferior a (análogo a <)
$test = 100
$teste -lt 123
-le
Menor ou igual a / Inferior ou igual a (análogo a <=)
$test = 100
$teste -le 123
Existem também outros operadores semelhantes que permitem, por exemplo, comparar strings considerando caracteres curinga ou usar expressões regulares para verificar correspondências. Abordaremos isso em detalhes nos próximos artigos. Os símbolos e = não são usados para comparação, pois são utilizados para outros fins.
Operadores de atribuição
Além do operador mais comum =, existem outros operadores de atribuição: +=, -=, *=, /= e %=. Eles alteram o valor antes da atribuição. Da mesma forma, os operadores unários ++ e — aumentam ou diminuem o valor da variável — também são considerados operadores de atribuição.
Operadores lógicos
Para descrever condições complexas, apenas a comparação não é suficiente. É possível escrever quaisquer expressões lógicas usando os operadores: -and, -or, -xor, -not e! ... Eles funcionam como em outras linguagens de programação, podendo-se usar parênteses para definir a ordem de cálculo:
("Teste" -eq "Teste") -and (100 -eq 100)
-not (123 -gt 321)
!(123 -gt 321)
Desvio condicional
Os operadores de ramificação no PowerShell são padrão: IF(IF…ELSE, IF…ELSEIF…ELSE) e SWITCH. Vamos examinar seu uso com exemplos:
[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 ou valor não definido"}
}
Loops
Na linguagem PowerShell, existem vários tipos de loops: WHILE, DO WHILE, DO UNTIL, FOR e FOREACH.
O loop com pré-condição funciona se/enquanto ele for verdadeiro:
[int]$test = 0
while ($test -lt 10) {
Write-Host $test
$test = $test + 1
}
Os loops com pós-condição serão executados pelo menos uma vez, pois a verificação da condição ocorre após a execução da iteração. O DO WHILE funciona enquanto a condição for verdadeira, e o DO UNTIL — enquanto for 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)
O número de iterações do loop FOR é conhecido de antemão:
for ([int]$test = 0; $test -lt 10; $test++) {
Write-Host $test
}
No loop FOREACH, realiza-se a iteração sobre os elementos de um array ou coleção (tabelas hash):
$test_collection = "item1", "item2", "item3"
foreach ($item in $test_collection)
{
Write-Host $item
}
Arrays
Nas variáveis de PowerShell, armazenam-se não apenas objetos individuais (número, string, etc.), mas também múltiplos. A forma mais simples dessas variáveis são arrays. Um array pode consistir em vários elementos, em um único elemento ou estar vazio, ou seja, não conter elementos. Para declarar um array, usa-se o operador @(), que será necessário no próximo artigo — é muito importante para adicionar outros arrays (criar arrays multidimensionais), passar arrays para funções como argumento e tarefas semelhantes:
$test_array = @() #criando um array vazioAo inicializar um array, seus valores são listados entre vírgulas (operador especial ,):
$test_array = @(1, 2, 3, 4) # cria um array com quatro elementos Na maioria dos casos, o operador @() pode ser omitido:
$test_array = 1, 2, 3, 4Nesse caso, um array de um único elemento é inicializado da seguinte forma
$test_array = , 1Para acessar os elementos de um array, usa-se um índice inteiro que começa em zero e o operador de índice (colchetes):
$test_array[0] = 1É possível especificar vários índices separados por vírgulas, incluindo repetidos:
$test_array = "um", "dois", "três", "quatro"
$test_array[0,1,2,3]
$test_array[1,1,3,3,0] 
Operador .. (dois pontos — operador de intervalo) retorna um array de inteiros com um limite superior e inferior definidos. Por exemplo, a expressão 1..4 gera um array com quatro elementos @(1, 2, 3, 4), enquanto a expressão 8..5 gera um array @(8, 7, 6, 5).

Com o operador de intervalo, é possível inicializar um array ($test_array = 1..4) ou obter uma fatia (slice), ou seja, uma sequência de elementos de um array com índices de outro. Nesse caso, um número negativo -1 representa o último elemento do array, -2 — o penúltimo, e assim por diante.
$test_array = "um", "dois", "três", "quatro"
$test_array[0..2]
$test_array[2..0]
$test_array[-1..0]
$test_array[-2..1]Observe que os valores do array inteiro podem ser maiores que o valor máximo do índice do array. Nesse caso, todos os valores até o último são retornados:
$test_array[0..100]Se você tentar acessar um único elemento inexistente no array, será retornado o valor $null.

No PowerShell, arrays podem conter elementos de tipos diferentes ou serem estritamente tipados:
$test_array = 1, 2, "teste", 3, 4
for ([int]$i = 0; $i -lt $test_array.count; $i++)
{
Write-Host $test_array[$i]
}
Onde a propriedade $test_array.count é o número de elementos do array.
Exemplo de criação de um array estritamente tipado:
[int[]]$test_array = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
Tabelas hash
Outro tipo básico de variável na linguagem PowerShell são as tabelas hash, que também são chamadas de arrays associativos. Hashtables são semelhantes a um objeto JSON e são construídos com base no princípio chave-valor. Diferente de arrays comuns, o acesso aos seus elementos é feito através de chaves nomeadas, que são propriedades do objeto (também é possível usar o operador de índice — colchetes).
Uma tabela hash vazia é declarada com o símbolo auxiliar @ e colchetes:
$test_hashtable = @{}Na declaração, é possível criar chaves e atribuir valores a elas imediatamente:
$test_hashtable = @{one="um"; two="dois"; three="três"; "some key"="some value"}Para adicionar um elemento à tabela hash, é necessário atribuir uma chave que ainda não exista ou usar o método Add(). Se a atribuição for feita com uma chave existente, seu valor será alterado. Para remover um elemento da tabela hash, utiliza-se o método Remove().
$test_hashtable."some key"
$test_hashtable["some key"]
$test_hashtable.Add("four", "quatro")
$test_hashtable.five = "cinco"
$test_hashtable['five'] = "trocando valor"
$test_hashtable.Remove("one") 
Variáveis desse tipo podem ser passadas como argumentos para funções e cmdlets — no próximo artigo, vamos explorar como isso é feito, assim como considerar um outro tipo semelhante — PSCustomObject.
Funções
A linguagem PowerShell contém todos os elementos necessários para a programação procedural, incluindo funções. A palavra-chave usada para descrevê-las é Function, seguida pelo nome da função e pelo corpo entre parênteses. Se for necessário passar argumentos para a função, eles podem ser indicados logo após o nome entre parênteses.
function nome-da-funcao (argumento1, ..., argumentoN)
{
corpo-da-funcao
}
Uma função sempre retorna um resultado — é um array de resultados de todas as suas instruções, se houver mais de uma. Se houver apenas uma instrução, retorna-se um único valor do tipo correspondente. A construção return $value adiciona um elemento com o valor $value ao array de resultados e interrompe a execução da lista de instruções, enquanto uma função vazia retorna $null.
Como exemplo, vamos criar uma função que eleva um número ao quadrado:
function sqr ($numero)
{
return $numero * $numero
}
Note que no corpo da função é possível usar quaisquer variáveis declaradas antes da sua chamada, e a chamada de funções em PowerShell pode parecer incomum: os argumentos (se existirem) não são colocados entre parênteses e são separados por espaços.
sqr 2ou assim:
sqr -number 2Devido à forma como os argumentos são passados, a função mesma às vezes precisa ser colocada entre parênteses:
function test_func ($n) {}
test_func -eq $null # a função não foi chamada
(test_func) -eq $null # o resultado da expressão é $true 
Ao descrever uma função, é possível atribuir valores padrão aos argumentos:
function func ($arg = value) {
#corpo da função
}
Existe também outra sintaxe para descrever argumentos da função, além do mais, parâmetros podem ser lidos do pipeline — tudo isso será útil no próximo artigo, quando abordaremos módulos exportados e a criação de nossos próprios cmdlets.
Manipulação de erros
No PowerShell, existe o mecanismo Try…Catch…Finally, que permite gerenciar situações excepcionais. O código que pode gerar um erro é colocado no bloco Try, enquanto o manipulador de erro vai no bloco Catch. Se não houver erro, o bloco Catch não é executado. O bloco Finally é executado após o bloco Try, independentemente de ocorrer um erro, e pode haver vários blocos Catch para diferentes tipos de exceções. A própria exceção é registrada em uma variável padrão que não requer declaração ($_) e pode ser facilmente extraída. No exemplo abaixo, implementamos uma proteção contra a entrada de um valor incorreto:
try {
[int]$test = Read-Host "Digite um número"
100 / $test
} catch {
Write-Warning "Número incorreto"
Write-Host $_
}

Com isso, encerramos a discussão sobre os conceitos básicos de programação na linguagem PowerShell. Nos próximos artigos, vamos explorar mais sobre o trabalho com variáveis de diferentes tipos, coleções, expressões regulares, criação de funções, módulos e scripts, além da programação orientada a objetos.
Fonte: habr.com
