Prévia do material em texto
08 Usando HashTables no PowerShell Alteraremos o script para indicar ao comando select que a expressão $nameExpr mudará o nome de Name para Nome, e o resultado da coluna Nome será uma expressão que pega somente a variável de interação, e retorna a propriedade Name. Faremos isso porque alteraremos o tipo dessa coluna, indicando qual expressão ela resulta, e o rótulo. Isso significa que não podemos mais usar uma string com o nome da propriedade, pois o select também irá colocar como rótulo esse mesmo nome. $nameExpr = "Nome", { $_.Name } $lengthExpr = "Tamanho", { "{0:N2}KB" -f ($_.Length / 1KB) } $params = $nameExpr, $lengthExpr gci -Recurse -File | ? Name -like "*_migrando_*" | select $params Nós também acrescentamos um label para o tamanho, e depois de pronto, vamos colar no PowerShell. Pressionaremos a tecla "Enter", e surgirá um erro: select : Não é possível converter System.Object[] para um dos seguintes tipos {System.String, System.Management.Automation.ScriptBlock}. O comando select não aceita como parâmetro um array de um array! É preciso deixar claro para ele quais são os nomes de cada valor que estamos passando como argumento. Se queremos indicar um objeto que terá chave e valor, podemos utilizar uma estrutura de dados conhecida como HashTable! Com o HashTable, será possível indicar ao PowerShell que a string Nome não é uma string qualquer, e sim uma string que precisa respeitar uma chave. A expressão { $_.Name } também não é mais um objeto jogado em nosso array. Ele também tem que respeitar uma chave esperada pelo comando select. E o HashTable nos da uma estrutura de dados para esse tipo de construção. Aprendemos na aula anterior que, podemos montar um array literalmente com a sintaxe @(). Para criarmos um HashTable, podemos usar @{}. Vamos testar no PowerShell? PS C:\Scripts> @{}.GetType().Name HashTable Podemos verificar também, quais são os métodos que temos disponíveis em um HashTable com o comando a seguir: PS C:\Scripts> @{} | Get-Member Temos o método Add cuja a definição é: void Add(System.Object key, System.Object value, void...). Adicionaremos chaves para o nosso HashTable. Será preciso dizer ao PowerShell que o objeto $nameExpr terá uma chave nova a partir do método .Add. Mas como vamos descobrir quais parâmetros temos que passar? Bom, é preciso ver esse método mais de perto, e também ver qual é o valor da coluna Definition, desta forma: PS C:\Scripts> (@{} | Get-Member -Name add).Definition O método Add possui dois parâmetros: a chave e o valor. Também possui um método de sobrecarga, onde ele recebe um objeto como chave e um outro objeto como valor vindos da interface IDictionary. void Add(System.Object key, System.Object value), void IDictionary.Add(System.Object key, System.Object value) Voltando na edição do nosso script, usaremos o Add para indicar que o rótulo (label) da coluna seja "Nome": $nameExpr = @{} $nameExpr.Add("Label", "Nome") Será necessário adicionar mais uma chave-valor que representará a expressão: $nameExpr = @{} $nameExpr.Add("Label", "Nome") $nameExpr.Add("Expression", { $_.Name }) Criaremos mais um HashTable, mas dessa vez para o tamanho do arquivo: $nameExpr = @{} $nameExpr.Add("Label", "Nome") $nameExpr.Add("Expression", { $_.Name }) $lengthExpr = @{} $lengthExpr.Add("Label", "Tamanho") $lengthExpr.Add("Expression", { "{0:N2}KB" -f ($_.Length / 1KB) }) $params = $nameExpr, $lengthExpr gci -Recurse -File | ? Name -like "*_migrando_*" | select $params Agora, copiamos esse código para tentarmos executá-lo. Como podemos ver, foi retornado da mesma forma que antes, mas como agora nós passamos como argumento um array de hashtable, o comando select conseguiu visitar cada um deles e verificar que temos uma chave *Label* e uma chave *Expression*, montando a partir delas, a tabela final. Entretanto, como podemos ver, essa sintaxe ficou um pouco carregada, não é mesmo? Tínhamos algo muito simples e, somente para colocar o nome do rótulo e a expressão de seu resultado, tivemos que chamar variáveis e chamar o método .Add e com isso, o código se tornou muito verboso. Para montar um literal de HashTable, temos também um outra alternativa mais simples. Veja o exemplo a seguir: $nameExpr = @{ Label = "Nome"; Expression = { $_.Name } } Aqui, nós inserimos a chave e o valor dos itens do HashTable. O primeiro item terá a chave Label e o seu valor é inserido depois do =. Utilizamos o ; para informar que iremos para o próximo item, e o PowerShell não exige um backtick nesse momento. O próximo item tem como a chave Expression e o seu valor é { $_.Name }, uma expressão que retorna apenas o nome do arquivo. Depois que terminamos de construir o HashTable, não é necessário colocar ; no último item. O mesmo processo é feito com o Length: $nameExpr = @{ Label = "Nome"; Expression = { $_.Name } } $lengthExpr = @{ Label = "Tamanho"; Expression = { "{0:N2}KB" -f ($_.Length / 1KB) } } $params = $nameExpr, $lengthExpr gci -Recurse -File | ? Name -like "*_migrando_*" | select $params Vamos tentar executar esse código no PowerShell? Maravilha! Mudamos a forma de construir o HashTable, usando a expressão literal, criando um HashTable no PowerShell utilizando a sintaxe suportada por ele, e colocamos exatamente a chave e o valor das entradas no HashTable. Muito melhor assim, não é verdade? 08 Usando HashTables no PowerShell