Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Matrizes são um recurso de linguagem fundamental da maioria das linguagens de programação. Eles são uma coleção de valores ou objetos que são difíceis de evitar. Vamos examinar as matrizes e tudo o que elas têm a oferecer.
Observação
A versão original deste artigo foi publicada no blog escrito por @KevinMarquette. A equipe do PowerShell agradece kevin por compartilhar este conteúdo conosco. Confira o blog dele no PowerShellExplained.com.
O que é uma matriz?
Vou começar com uma descrição técnica básica do que são matrizes e como elas são usadas pela maioria das linguagens de programação antes de mudar para as outras maneiras pelas quais o PowerShell faz uso delas.
Uma matriz é uma estrutura de dados que serve como uma coleção de vários itens. Você pode iterar pela matriz ou acessar itens individuais usando um índice. A matriz é criada como uma parte sequencial da memória em que cada valor é armazenado ao lado do outro.
Vou tocar em cada um desses detalhes à medida que avançamos.
Uso Básico
Como as matrizes são um recurso básico do PowerShell, há uma sintaxe simples para trabalhar com elas no PowerShell.
Criar uma matriz
Uma matriz vazia pode ser criada usando @()
PS> $data = @()
PS> $data.Count
0
Podemos criar uma matriz e inicializá-la com valores simplesmente colocando-os nos parênteses @().
PS> $data = @('Zero','One','Two','Three')
PS> $data.Count
4
PS> $data
Zero
One
Two
Three
Essa matriz tem 4 itens. Quando chamamos a variável $data, vemos a lista de nossos itens. Se for uma matriz de cadeias de caracteres, obteremos uma linha por cadeia de caracteres.
Podemos declarar uma matriz em várias linhas. A vírgula é opcional nesse caso e geralmente é deixada de fora.
$data = @(
'Zero'
'One'
'Two'
'Three'
)
Prefiro declarar minhas matrizes em várias linhas como essa. Além de ficar mais fácil de ler quando você tem vários itens, também facilita a comparação com versões anteriores ao usar o controle do código-fonte.
Outra sintaxe
Normalmente, entende-se que @() é a sintaxe para criar uma matriz, mas as listas separadas por vírgula funcionam na maior parte do tempo.
$data = 'Zero','One','Two','Three'
Write-Output para criar matrizes
Um truque interessante que vale a pena mencionar é que você pode usar Write-Output para criar cadeias de caracteres rapidamente no console.
$data = Write-Output Zero One Two Three
Isso é útil porque você não precisa colocar aspas em torno das cadeias de caracteres quando o parâmetro aceita cadeias de caracteres. Eu nunca faria isso em um script, mas é aceitável no console.
Acessar itens
Agora que você tem uma matriz com itens, convém acessar e atualizar esses itens.
Offset
Para acessar itens individuais, usamos os colchetes [] com um valor de deslocamento começando em 0. É assim que obtemos o primeiro item em nossa matriz:
PS> $data = 'Zero','One','Two','Three'
PS> $data[0]
Zero
O motivo pelo qual usamos zero aqui é porque o primeiro item está no início da lista, portanto, usamos um deslocamento de 0 itens para chegar a ele. Para chegar ao segundo item, precisamos usar um deslocamento de 1 para ignorar o primeiro item.
PS> $data[1]
One
Isso significa que o último item está no deslocamento 3.
PS> $data[3]
Three
Índice
Agora você pode ver por que escolhi os valores que fiz para este exemplo. Apresentei a você como um deslocamento porque realmente é, mas esse deslocamento é mais comumente chamado de índice. Um índice que começa em 0. No restante deste artigo, chamarei o deslocamento de índice.
Truques especiais de índice
Na maioria dos idiomas, você só pode especificar um único número como o índice e obter um único item de volta. O PowerShell é muito mais flexível. Você pode usar vários índices ao mesmo tempo. Ao fornecer uma lista de índices, podemos selecionar vários itens.
PS> $data[0,2,3]
Zero
Two
Three
Os itens são retornados com base na ordem dos índices fornecidos. Se você duplicar um índice, obterá esse item em ambas as vezes.
PS> $data[3,0,3]
Three
Zero
Three
Podemos especificar uma sequência de números com o operador .. interno.
PS> $data[1..3]
One
Two
Three
Isso também funciona inverso.
PS> $data[3..1]
Three
Two
One
Você pode usar valores de índice negativos para começar o deslocamento do final. Portanto, se você precisar do último item da lista, poderá usar -1.
PS> $data[-1]
Three
Tenha cuidado com o operador ... As sequências 0..-1 e -1..0 avaliam os valores 0,-1 e -1,0. É fácil ver $data[0..-1] e pensar que ele enumerará todos os itens se você esquecer esse detalhe. $data[0..-1] fornece o mesmo valor que $data[0,-1] fornecendo o primeiro e o último item na matriz (e nenhum dos outros valores). Aqui está um exemplo maior:
PS> $a = 1,2,3,4,5,6,7,8
PS> $a[2..-1]
3
2
1
8
Isso é o mesmo que:
PS> $a[2,1,0,-1]
3
2
1
8
Fora dos limites
Na maioria dos idiomas, se você tentar acessar um índice de um item que já passou do final da matriz, você obterá algum tipo de erro ou uma exceção. O PowerShell silenciosamente não retorna nada.
PS> $null -eq $data[9000]
True
Não é possível indexar em uma matriz nula
Se a variável for $null e você tentar indexá-la como uma matriz, você obterá uma exceção System.Management.Automation.RuntimeException com a mensagem Cannot index into a null array.
PS> $empty = $null
PS> $empty[0]
Error: Cannot index into a null array.
Portanto, verifique se suas matrizes não estão $null antes de tentar acessar elementos dentro delas.
Contagem
Matrizes e outras coleções têm uma propriedade Count que informa quantos itens estão na matriz.
PS> $data.Count
4
O PowerShell 3.0 adicionou uma propriedade Count à maioria dos objetos. Você pode ter apenas um objeto e ele deve fornecer uma contagem de 1.
PS> $date = Get-Date
PS> $date.Count
1
Até mesmo $null tem uma propriedade Count, porém ela retorna 0.
PS> $null.Count
0
Existem algumas armadilhas aqui que vou revisitar posteriormente quando abordar a verificação de $null ou de matrizes vazias neste artigo.
Erros por falta de uma repetição
Um erro de programação comum é criado porque as matrizes começam no índice 0. Os erros por falta de uma repetição podem ser introduzidos pensando em duas situações.
A primeira ocorre quando você pensa em obter o segundo item e usa um índice de 2, o que faz com que você obtenha o terceiro item. Ou quando você usa a contagem para acessar o último item em uma matriz de quatro itens.
$data[ $data.Count ]
O PowerShell está perfeitamente feliz em permitir que você faça isso e forneça exatamente qual item existe no índice 4: $null. Você deve estar usando $data.Count - 1 ou o -1 sobre o qual aprendemos acima.
PS> $data[ $data.Count - 1 ]
Three
É aqui que você pode usar o índice -1 para obter o último elemento.
PS> $data[ -1 ]
Three
Lee Dailey também me apontou que podemos usar $data.GetUpperBound(0) para obter o número máximo do índice.
PS> $data.GetUpperBound(0)
3
PS> $data[ $data.GetUpperBound(0) ]
Three
A segunda maneira mais comum é ao iterar a lista e não parar no momento certo. Vou revisitar isso quando falarmos sobre como usar o loop for.
Atualizando itens
Podemos usar o mesmo índice para atualizar itens existentes na matriz. Isso nos dá acesso direto para atualizar itens individuais.
$data[2] = 'dos'
$data[3] = 'tres'
Se tentarmos atualizar um item que já passou do último elemento, teremos um erro de Index was outside the bounds of the array..
PS> $data[4] = 'four'
Index was outside the bounds of the array.
At line:1 char:1
+ $data[4] = 'four'
+ ~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], IndexOutOfRangeException
+ FullyQualifiedErrorId : System.IndexOutOfRangeException
Vou retomar isso mais tarde, quando falar sobre como expandir uma matriz.
Iteração
Em algum momento, talvez seja necessário percorrer ou iterar toda a lista e executar alguma ação para cada item no array.
Pipeline
As matrizes e o pipeline do PowerShell são uma combinação perfeita. Essa é uma das maneiras mais simples de processar esses valores. Quando você passa uma matriz para um pipeline, cada item dentro da matriz é processado individualmente.
PS> $data = 'Zero','One','Two','Three'
PS> $data | ForEach-Object {"Item: [$PSItem]"}
Item: [Zero]
Item: [One]
Item: [Two]
Item: [Three]
Se você não viu $PSItem antes, apenas saiba que é a mesma coisa que $_. Você pode usar um deles porque ambos representam o objeto atual no pipeline.
Loop ForEach
O loop foreach funciona bem com coleções. Usando a sintaxe: foreach ( <variable> in <collection> )
foreach ( $node in $data )
{
"Item: [$node]"
}
Método ForEach
Eu costumo esquecer este, mas funciona bem para operações simples. O PowerShell permite que você chame ForEach() em uma coleção.
PS> $data.ForEach({"Item [$PSItem]"})
Item [Zero]
Item [One]
Item [Two]
Item [Three]
O ForEach() usa um parâmetro que é um bloco de script. Você pode remover os parênteses e apenas fornecer o bloco de script.
$data.ForEach{"Item [$PSItem]"}
Esta é uma sintaxe menos conhecida, mas funciona da mesma forma. Esse método ForEach foi adicionado no PowerShell 4.0.
Loop for
O loop for é usado fortemente na maioria dos outros idiomas, mas você não o vê muito no PowerShell. Geralmente ele é usado para percorrer uma matriz.
for ( $index = 0; $index -lt $data.Count; $index++)
{
"Item: [{0}]" -f $data[$index]
}
A primeira coisa que fazemos é inicializar um $index para 0. Em seguida, adicionamos a condição de que $index deve ser menor que $data.Count. Por fim, especificamos que, toda vez que repetirmos o loop, devemos aumentar o índice em 1. Nesse caso, $index++ é abreviação de $index = $index + 1. O operador de formato (-f) é usado para inserir o valor de $data[$index] na cadeia de caracteres de saída.
Sempre que você estiver usando um loop for, preste muita atenção à condição. Eu usei $index -lt $data.Count aqui. É fácil obter uma condição um pouco errada para obter um erro por falta de uma repetição em sua lógica. Usar $index -le $data.Count ou $index -lt ($data.Count - 1) é ligeiramente incorreto. Isso faria com que seu resultado processasse itens em excesso ou insuficientemente. Este é o clássico erro por falta de uma repetição.
Loop switch
Este é um que é fácil de ignorar. Se você fornecer uma matriz a uma instrução de comutador , ela verificará cada item na matriz.
$data = 'Zero','One','Two','Three'
switch( $data )
{
'One'
{
'Tock'
}
'Three'
{
'Tock'
}
Default
{
'Tick'
}
}
Tick
Tock
Tick
Tock
Há muitas coisas interessantes que podemos fazer com a instrução switch. Tenho outro artigo dedicado a isso.
Atualizando valores
Quando sua matriz é uma coleção de cadeias de caracteres ou inteiros (tipos de valor), às vezes, talvez você queira atualizar os valores na matriz enquanto faz loop sobre eles. A maioria dos loops acima usa uma variável no loop que contém uma cópia do valor. Se você atualizar essa variável, o valor original na matriz não será atualizado.
A exceção a essa instrução é o loop for. Se você quiser percorrer uma matriz e atualizar valores dentro dela, o loop for é o que você está procurando.
for ( $index = 0; $index -lt $data.Count; $index++ )
{
$data[$index] = "Item: [{0}]" -f $data[$index]
}
Este exemplo usa um valor por índice, faz algumas alterações e usa o mesmo índice para atribuí-lo de volta.
Matrizes de objetos
Até agora, a única coisa que colocamos em uma matriz é um tipo de valor, mas as matrizes também podem conter objetos.
$data = @(
[pscustomobject]@{FirstName='Kevin';LastName='Marquette'}
[pscustomobject]@{FirstName='John'; LastName='Doe'}
)
Muitos cmdlets retornam coleções de objetos como matrizes quando você os atribui a uma variável.
$processList = Get-Process
Todos os recursos básicos sobre os quais já falamos ainda se aplicam a matrizes de objetos com alguns detalhes que vale a pena apontar.
Acessar propriedades
Podemos usar um índice para acessar um item individual em uma coleção, assim como com tipos de valor.
PS> $data[0]
FirstName LastName
----- ----
Kevin Marquette
Podemos acessar e atualizar as propriedades diretamente.
PS> $data[0].FirstName
Kevin
PS> $data[0].FirstName = 'Jay'
PS> $data[0]
FirstName LastName
----- ----
Jay Marquette
Propriedades da matriz
Normalmente, você teria que enumerar toda a lista como esta para acessar todas as propriedades:
PS> $data | ForEach-Object {$_.LastName}
Marquette
Doe
Ou usando o cmdlet Select-Object -ExpandProperty.
PS> $data | Select-Object -ExpandProperty LastName
Marquette
Doe
Mas o PowerShell nos oferece a capacidade de solicitar LastName diretamente. O PowerShell enumera todos eles para nós e retorna uma lista limpa.
PS> $data.LastName
Marquette
Doe
A enumeração ainda acontece, mas não vemos a complexidade por trás dela.
Filtragem Where-Object
É aí que Where-Object entra para que possamos filtrar e selecionar o que queremos fora da matriz com base nas propriedades do objeto.
PS> $data | Where-Object {$_.FirstName -eq 'Kevin'}
FirstName LastName
----- ----
Kevin Marquette
Podemos gravar essa mesma consulta para obter o FirstName que estamos procurando.
$data | where FirstName -EQ Kevin
Where()
As matrizes têm um método Where() neles que permite especificar um scriptblock para o filtro.
$data.Where({$_.FirstName -eq 'Kevin'})
Esse recurso foi adicionado ao PowerShell 4.0.
Atualizando objetos em loops
Com tipos de valor, a única maneira de atualizar a matriz é usar um loop for porque precisamos saber o índice para substituir o valor. Temos mais opções com objetos porque eles são tipos de referência. Aqui está um exemplo rápido:
foreach($person in $data)
{
$person.FirstName = 'Kevin'
}
Esse loop está percorrendo todos os objetos na matriz $data. Como os objetos são tipos de referência, a variável $person faz referência exatamente ao mesmo objeto que está na matriz. Portanto, as atualizações das suas propriedades atualizam o original.
Você ainda não pode substituir todo o objeto dessa maneira. Se você tentar atribuir um novo objeto à variável $person, atualizará a referência de variável para outra coisa que não aponta mais para o objeto original na matriz. Isso não funciona como você esperaria:
foreach($person in $data)
{
$person = [pscustomobject]@{
FirstName='Kevin'
LastName='Marquette'
}
}
Operadores
Os operadores no PowerShell também funcionam em matrizes. Alguns deles funcionam um pouco diferente.
-join
O operador -join é o mais óbvio, então vamos vê-lo primeiro. Gosto do operador -join e uso-o com frequência. Ele une todos os elementos na matriz com o caractere ou cadeia de caracteres que você especificar.
PS> $data = @(1,2,3,4)
PS> $data -join '-'
1-2-3-4
PS> $data -join ','
1,2,3,4
Um dos recursos que eu gosto no operador -join é que ele lida com itens únicos.
PS> 1 -join '-'
1
Uso isso dentro de mensagens detalhadas e de registro em log.
PS> $data = @(1,2,3,4)
PS> "Data is $($data -join ',')."
Data is 1,2,3,4.
-join $array
Aqui está um truque inteligente que Lee Dailey me apontou. Se você quiser juntar todos os elementos sem um delimitador, em vez de fazer isso:
PS> $data = @(1,2,3,4)
PS> $data -join $null
1234
Você pode usar -join com a matriz como parâmetro, sem prefixo. Dê uma olhada neste exemplo para entender sobre o que estou falando.
PS> $data = @(1,2,3,4)
PS> -join $data
1234
-replace e -split
Os outros operadores, como -replace e -split, são executados em cada item na matriz. Não posso dizer que já os usei dessa maneira, mas aqui está um exemplo.
PS> $data = @('ATX-SQL-01','ATX-SQL-02','ATX-SQL-03')
PS> $data -replace 'ATX','LAX'
LAX-SQL-01
LAX-SQL-02
LAX-SQL-03
-contains
O operador -contains permite verificar uma matriz de valores para ver se ele contém um valor especificado.
PS> $data = @('red','green','blue')
PS> $data -contains 'green'
True
-in
Quando você tiver um único valor que gostaria de verificar se corresponde a um dos vários valores, você pode usar o operador -in. O valor estaria à esquerda e a matriz no lado direito do operador.
PS> $data = @('red','green','blue')
PS> 'green' -in $data
True
Isso pode ficar caro se a lista for grande. Geralmente uso um padrão regex se estiver verificando mais do que alguns valores.
PS> $data = @('red','green','blue')
PS> $pattern = "^({0})$" -f ($data -join '|')
PS> $pattern
^(red|green|blue)$
PS> 'green' -match $pattern
True
-eq e -ne
Igualdade e matrizes podem ficar complicadas. Quando a matriz está no lado esquerdo, cada item é comparado. Em vez de retornar True, ele retorna o objeto que corresponde.
PS> $data = @('red','green','blue')
PS> $data -eq 'green'
green
Quando você usa o operador -ne, obtemos todos os valores que não são iguais ao nosso valor.
PS> $data = @('red','green','blue')
PS> $data -ne 'green'
red
blue
Quando você usa isso em uma instrução if(), um valor retornado é um valor True. Se nenhum valor for retornado, será um valor False. Ambas as próximas instruções são avaliadas como True.
$data = @('red','green','blue')
if ( $data -eq 'green' )
{
'Green was found'
}
if ( $data -ne 'green' )
{
'And green was not found'
}
Retornarei a este assunto daqui a pouco quando falarmos sobre testes para $null.
-match
O operador -match tenta obter uma correspondência para cada item na coleção.
PS> $servers = @(
'LAX-SQL-01'
'LAX-API-01'
'ATX-SQL-01'
'ATX-API-01'
)
PS> $servers -match 'SQL'
LAX-SQL-01
ATX-SQL-01
Quando você usa -match com um único valor, uma variável especial $Matches é preenchida com informações de correspondência. Esse não é o caso quando uma matriz é processada dessa forma.
Podemos adotar a mesma abordagem com Select-String.
$servers | Select-String SQL
Dou uma olhada mais de perto em Select-String,-match e a variável $Matches em outro post chamado As várias maneiras de usar o regex.
$null ou vazio
O teste para matrizes $null ou vazias pode ser complicado. Aqui estão as armadilhas mais comuns com matrizes.
À primeira vista, essa instrução parece funcionar.
if ( $array -eq $null)
{
'Array is $null'
}
Mas eu acabei de verificar como -eq verifica cada item na matriz. Portanto, podemos ter uma matriz de vários itens com um único valor $null e ele seria avaliado como $true
$array = @('one',$null,'three')
if ( $array -eq $null)
{
'I think Array is $null, but I would be wrong'
}
É por isso que é uma prática recomendada colocar o $null no lado esquerdo do operador. Isso torna esse cenário irrelevante.
if ( $null -eq $array )
{
'Array actually is $null'
}
Uma matriz $null não é a mesma coisa que uma matriz vazia. Se você souber que tem uma matriz, verifique a contagem de objetos nela. Se a matriz for $null, a contagem será 0.
if ( $array.Count -gt 0 )
{
"Array isn't empty"
}
Há mais uma armadilha para tomar cuidado aqui. Você pode usar o Count mesmo se tiver um único objeto, a menos que esse objeto seja um PSCustomObject. Esse é um bug corrigido no PowerShell 6.1.
Isso é uma boa notícia, mas muitas pessoas ainda estão na 5.1 e precisam tomar cuidado com isso.
PS> $object = [pscustomobject]@{Name='TestObject'}
PS> $object.Count
$null
Se você ainda estiver no PowerShell 5.1, poderá encapsular o objeto em uma matriz antes de verificar a contagem para obter uma contagem precisa.
if ( @($array).Count -gt 0 )
{
"Array isn't empty"
}
Para não correr nenhum risco, verifique se há $null e, em seguida, verifique a contagem.
if ( $null -ne $array -and @($array).Count -gt 0 )
{
"Array isn't empty"
}
Tudo -eq
Recentemente, vi alguém no Reddit perguntar como verificar se cada valor em uma matriz corresponde a um determinado valor. O usuário do Reddit u/bis tinha essa solução inteligente que verifica se há valores incorretos e, em seguida, inverte o resultado.
$results = Test-Something
if ( -not ( $results -ne 'Passed') )
{
'All results a Passed'
}
Adicionar a matrizes
Neste ponto, você está começando a se perguntar como adicionar itens a uma matriz. A resposta rápida é que você não pode. Uma matriz é um tamanho fixo na memória. Se você precisar ampliá-lo ou adicionar um único item a ele, será necessário criar uma nova matriz e copiar todos os valores da matriz antiga. Isso parece muito trabalho, no entanto, o PowerShell oculta a complexidade de criar a nova matriz. O PowerShell implementa o operador de adição (+) para matrizes.
Observação
O PowerShell não implementa uma operação de subtração. Se você quiser uma alternativa flexível a uma matriz, precisará usar um objeto List genérico.
Adição de matriz
Podemos usar o operador de adição com matrizes para criar uma nova matriz. Portanto, considerando estas duas matrizes:
$first = @(
'Zero'
'One'
)
$second = @(
'Two'
'Three'
)
Podemos adicioná-los para obter uma nova matriz.
PS> $first + $second
Zero
One
Two
Three
Mais igual +=
Podemos criar uma nova matriz no local e adicionar um item a ela da seguinte maneira:
$data = @(
'Zero'
'One'
'Two'
'Three'
)
$data += 'four'
Basta lembrar que, sempre que você usa +=, está duplicando e criando uma nova matriz. Esse não é um problema para pequenos conjuntos de dados, mas sua escalabilidade é extremamente ruim.
Atribuição de pipeline
Você pode atribuir os resultados de qualquer pipeline em uma variável. É uma matriz se contiver vários itens.
$array = 1..5 | ForEach-Object {
"ATX-SQL-$PSItem"
}
Normalmente, quando pensamos em usar o pipeline, consideramos os comandos de uma linha típicos do PowerShell. Podemos aproveitar o pipeline com instruções foreach() e outros loops. Portanto, em vez de adicionar itens a uma matriz em um loop, podemos soltar itens no pipeline.
$array = foreach ( $node in (1..5))
{
"ATX-SQL-$node"
}
Tipos de matriz
Por padrão, uma matriz no PowerShell é criada como um tipo de [psobject[]]. Isso permite que ele contenha qualquer tipo de objeto ou valor. Isso funciona porque tudo é herdado do tipo PSObject.
Matrizes fortemente tipadas
Você pode criar uma matriz de qualquer tipo usando uma sintaxe semelhante. Quando você cria uma matriz fortemente tipada, ela só pode conter valores ou objetos do tipo especificado.
PS> [int[]] $numbers = 1,2,3
PS> [int[]] $numbers2 = 'one','two','three'
ERROR: Cannot convert value "one" to type "System.Int32". Input string was not in a correct format."
PS> [string[]] $strings = 'one','two','three'
ArrayList
Adicionar itens a uma matriz é uma de suas maiores limitações, mas há algumas outras coleções que podemos recorrer para resolver esse problema.
O ArrayList geralmente é uma das primeiras coisas que pensamos quando precisamos de uma matriz com a qual é mais rápido trabalhar. Ele age como uma matriz de objetos em todos os lugares em que precisamos, mas lida com a adição de itens rapidamente.
Veja como criamos um ArrayList e adicionamos itens a ele.
$myarray = [System.Collections.ArrayList]::new()
[void]$myArray.Add('Value')
Estamos chamando o .NET para obter este tipo. Nesse caso, estamos usando o construtor padrão para criá-lo. Em seguida, chamamos o método Add para adicionar um item a ele.
O motivo pelo qual estou usando [void] no início da linha é suprimir o código de retorno. Algumas chamadas do .NET fazem isso e podem criar uma saída inesperada.
Se os únicos dados que você tem em sua matriz forem cadeias de caracteres, também considere o uso de StringBuilder. É quase a mesma coisa, mas alguns métodos são usados apenas para lidar com cadeias de caracteres. O StringBuilder foi especialmente projetado para desempenho.
É comum ver as pessoas migrarem para ArrayList de matrizes. Mas vem de uma época em que o C# não tinha suporte genérico. O ArrayList é preterido em favor ao List[] genérico
Lista genérica
Um tipo genérico é um tipo especial em C# que define uma classe generalizada e o usuário especifica os tipos de dados que usa quando criado. Portanto, se você quiser uma lista de números ou cadeias de caracteres, você definirá que deseja listar tipos de int ou string.
Veja como você cria uma lista para cadeias de caracteres.
$mylist = [System.Collections.Generic.List[string]]::new()
Ou uma lista de números.
$mylist = [System.Collections.Generic.List[int]]::new()
Podemos converter uma matriz existente em uma lista como esta sem criar o objeto primeiro:
$mylist = [System.Collections.Generic.List[int]]@(1,2,3)
Podemos reduzir a sintaxe com a instrução using namespace no PowerShell 5 e mais recente. A instrução using precisa ser a primeira linha do script. Ao declarar um namespace, o PowerShell permite que você o deixe fora dos tipos de dados ao referenciá-los.
using namespace System.Collections.Generic
$myList = [List[int]]@(1,2,3)
Isso torna o List muito mais utilizável.
Você tem um método Add semelhante disponível para você. Ao contrário do ArrayList, não há nenhum valor retornado no método Add, portanto, não precisamos void-lo.
$myList.Add(10)
E ainda podemos acessar os elementos como outras matrizes.
PS> $myList[-1]
10
List[psobject]
Você pode ter uma lista de qualquer tipo, mas quando não souber o tipo de objetos, poderá usar [List[psobject]] para contê-los.
$list = [List[psobject]]::new()
Remove()
O ArrayList e o List[] genérico dão suporte à remoção de itens da coleção.
using namespace System.Collections.Generic
$myList = [List[string]]@('Zero','One','Two','Three')
[void]$myList.Remove("Two")
Zero
One
Three
Ao trabalhar com tipos de valor, ele remove o primeiro da lista. Você pode chamá-la repetidamente para continuar a remover esse valor. Se você tiver tipos de referência, precisará fornecer o objeto que deseja remover.
[List[System.Management.Automation.PSDriveInfo]]$drives = Get-PSDrive
$drives.Remove($drives[2])
$delete = $drives[2]
$drives.Remove($delete)
O método remove retorna true se ele foi capaz de localizar e remover o item da coleção.
Mais coleções
Há muitas outras coleções que podem ser usadas, mas essas são as melhores substituições genéricas para matriz. Se você tiver interesse em saber mais sobre essas opções, dê uma olhada neste Gist que Mark Kraus reuniu.
Outras nuances
Agora que cobri todas as principais funcionalidades, aqui estão mais algumas coisas que eu queria mencionar antes de encerrar isso.
Matrizes pré-dimensionadas
Mencionei que você não pode alterar o tamanho de uma matriz depois que ela é criada. Podemos criar uma matriz de um tamanho pré-determinado chamando-a com o construtor new($size).
$data = [Object[]]::new(4)
$data.Count
4
Multiplicando matrizes
Um truque interessante é que você pode multiplicar uma matriz por um inteiro.
PS> $data = @('red','green','blue')
PS> $data * 3
red
green
blue
red
green
blue
red
green
blue
Inicializar com 0
Um cenário comum é que você deseja criar uma matriz com todos os zeros. Se você for ter apenas inteiros, uma matriz fortemente tipada de inteiros assumirá como padrão todos os zeros.
PS> [int[]]::new(4)
0
0
0
0
Podemos usar o truque de multiplicação para fazer isso também.
PS> $data = @(0) * 4
PS> $data
0
0
0
0
A coisa boa sobre o truque de multiplicação é que você pode usar qualquer valor. Portanto, se você preferir ter 255 como seu valor padrão, essa seria uma boa maneira de fazê-lo.
PS> $data = @(255) * 4
PS> $data
255
255
255
255
Matrizes aninhadas
Uma matriz dentro de uma matriz é chamada de matriz aninhada. Não uso muito no PowerShell, mas os usei mais em outras linguagens. Considere o uso de uma matriz de matrizes quando seus dados couberem em um padrão tipo grade.
Aqui estão duas maneiras de criar uma matriz bidimensional.
$data = @(@(1,2,3),@(4,5,6),@(7,8,9))
$data2 = @(
@(1,2,3),
@(4,5,6),
@(7,8,9)
)
A vírgula é muito importante nesses exemplos. Dei um exemplo anterior de uma matriz normal em várias linhas em que a vírgula era opcional. Esse não é o caso de uma matriz multidimensional.
A maneira como usamos a notação de índice muda ligeiramente agora que temos uma matriz aninhada. Usando o $data acima, é assim que acessaríamos o valor 3.
PS> $outside = 0
PS> $inside = 2
PS> $data[$outside][$inside]
3
Adicione um conjunto de colchetes para cada nível de aninhamento de matriz. O primeiro conjunto de colchetes é para a matriz mais externa e, em seguida, você continua o processo de lá.
Write-Output -NoEnumerate
O PowerShell gosta de desembrulhar ou enumerar matrizes. Esse é um aspecto central da maneira como o PowerShell usa o pipeline, mas há momentos em que você não quer que isso aconteça.
Normalmente, redireciono objetos para Get-Member para saber mais sobre eles. Quando redireciono uma matriz para ele, ela é desencapsulada e Get-Member vê os membros da matriz e não a matriz real.
PS> $data = @('red','green','blue')
PS> $data | Get-Member
TypeName: System.String
...
Para evitar o desencapsulamento da matriz, você pode usar Write-Output -NoEnumerate.
PS> Write-Output -NoEnumerate $data | Get-Member
TypeName: System.Object[]
...
Eu tenho uma segunda maneira que é mais um hack (e eu tento evitar hacks como este). Você pode inserir uma vírgula na frente da matriz antes de redirecioná-la. Isso envolve $data em outro array onde ele é o único elemento, então, após desembrulhar o array externo, obtemos $data desembrulhado.
PS> ,$data | Get-Member
TypeName: System.Object[]
...
Retornar uma matriz
Esse desencapsulamento de matrizes também acontece quando você gera ou retorna valores de uma função. Você ainda poderá obter uma matriz se atribuir a saída a uma variável para que isso não seja geralmente um problema.
A questão é que você tem uma nova matriz. Se esse for um problema, você pode usar Write-Output -NoEnumerate $array ou return ,$array para contornar isso.
Mais alguma coisa?
Sei que é muita informação a ser assimilada. Espero que você aprenda algo com este artigo toda vez que o ler e que ele seja uma boa referência para você por muito tempo. Se você achou isso útil, compartilhe-o com outras pessoas que você acha que podem obter valor com ele.
Daqui em diante, recomendo que você confira uma postagem semelhante que escrevi sobre tabelas de hash.