Como decifrar a sintaxe do Powershell para formatação de texto?

4

Encontrei um script do PowerShell que achei que poderia adaptar aos meus propósitos.

Ele contém essa linha que formata a saída:

$largeSizefiles = get-ChildItem -path $filesLocation -include $Extension -recurse -ErrorAction "SilentlyContinue" | ? { $_.GetType().Name -eq "FileInfo" } | where-Object {$_.Length -gt $fileSize} | sort-Object -property length  | Select-Object Name, @{Name="Size In KB";Expression={ "{0:N0}" -f ($_.Length / 1KB)}},@{Name="LastWriteTime";Expression={$_.LastWriteTime}},@{Name="Path";Expression={$_.directory}} -first $filesLimit

A parte chave parece ser esta:

Select-Object Name, @{Name="Size In KB";Expression={ "{0:N0}" -f ($_.Length / 1KB)}},@{Name="LastWriteTime";Expression={$_.LastWriteTime}},@{Name="Path";Expression={$_.directory}} -first $filesLimit

Eu li o tutorial ss64.com em Select-Object, mas não encontro nada para explicar como as expressões do formulário @ {.....} estão formatando o texto.

A página ss64.com no operador @ mostra-a no formato @ (...), com parênteses, não suspensórios.

O código acima resulta na seguinte saída:

Name          : RPI-Image-1-Copy.img
Size In MB    : 29,477
Path          : D:\VirtualDriveShare
LastWriteTime : 8/18/2015 6:27:51 PM

Estou familiarizado com várias linguagens de programação, mas isso não é óbvio para mim e não encontrei nenhuma explicação clara on-line. Alguém pode me indicar um bom tutorial?

    
por tim11g 19.10.2016 / 19:43

4 respostas

6

O Select-Object pode usar uma tabela de hash de Cabeçalho / Valores para cada item. Neste exemplo:

Select-Object Name, @{Name="Size In KB";Expression={ "{0:N0}" -f ($_.Length / 1KB)}} ...

o script está selecionando Nome e, em seguida, "Nome em KB" que é derivado do parâmetro Comprimento do objeto de pipeline atual.

Isso é formatado primeiro dividindo-o primeiro por 1024 e usando {0: N0} para exibi-lo.

O Powershell usa a sintaxe de formato de string .Net para exibição - nesse caso, {0: N0} se traduz em:

// N or n (Number): It represent how many decimal places of zeros to show.
String.Format("{0:N4}", pos);      //”10.0000″

Você pode querer dar uma olhada nos artigos Format 101 e Format 102 de Kathy Kam:

para mais detalhes sobre formatação de strings.

    
por 19.10.2016 / 20:59
2

O que você está perdendo é que @{...} indica uma matriz hashtable, composta de pares de valores-chave.

Como apontado nos comentários, há um artigo da Technet sobre isso . No seu exemplo, o que está acontecendo é que o nome / título está sendo atribuído à chave na hashtable, e uma variável com uma expressão de formatação está sendo atribuída ao valor na hashtable.

Hashtables no PowerShell são bastante simples, mas no caso de ser útil, a página do ss64 está aqui , e O Technet também tem uma página de tutorial .

    
por 19.10.2016 / 20:47
2

Concordo com todas as outras respostas, sendo a tabela de hash uma propriedade calculada neste caso. Acho maravilhosos esses forros, mas eles poderiam ser apresentados de uma maneira muito melhor. Técnico ainda um one-liner mas legibilidade em uma escala diferente.

$largeSizefiles = get-ChildItem '
    -path $filesLocation '
    -include $Extension '
    -recurse '
    -ErrorAction "SilentlyContinue" | 
  Where-object { ($_.GetType().Name -eq "FileInfo") '
            -and ($_.Length -gt $fileSize)} | 
  sort-Object -property length  | 
  Select-Object Name, 
    @{Name="Size In KB";Expression={ "{0:N0}" -f ($_.Length / 1KB)}}, 
    @{Name="LastWriteTime";Expression={$_.LastWriteTime}}, 
    @{Name="Path";Expression={$_.directory}} -first $filesLimit

Se PoSh esperar uma continuação (depois de um , ou um | ) você pode simplesmente inserir uma nova linha ou, claro, após a continuação da linha, caractere o backtic '.

    
por 19.10.2016 / 21:31
2

@{...=...; ...=...} é uma hashtable . Você pode conhecê-los como "dicionários" em outros idiomas. Estes são pares chave / valor. Os pontos-e-vírgulas ( ; ) separam os diferentes pares, e a chave e o valor são separados por um sinal de igual ( = ). Note que a chave pode ter citações implícitas, tornando-a uma string.

A parte { "{0:N0}" -f ($_.Length / 1KB) } é um bloco de script . Há um monte desses; todas as chaves Expression nas tabelas de hash são mapeadas para uma. Você pode dizer isso pelas chaves sem um prefixo em torno dele. Estas são essencialmente funções anônimas (lambdas). O $_ é o item atual do pipeline, portanto, quando esse bloco de script é executado, ele é expandido para um único item a partir da entrada do pipeline.

O bloco de script em particular "{0:N0}" -f ($_.Length / 1KB) part está apenas usando o % operador de-f para fazer a formatação . Isso equivale ao String.Format do .NET, onde a cadeia padrão está à esquerda e os argumentos para o padrão são uma matriz de objetos à direita. O 0 é apenas o índice do argumento (portanto, primeiro argumento) e o :N0 indica que ele deve ser formatado como um número com 0 casas decimais.

Agora, entre todas as hashtables, temos um monte de vírgulas. Isso cria uma matriz ! Acontece que a parte @(...) circundante é opcional.

Portanto, temos um array contendo algumas strings e um monte de hashtables com as chaves Name e Expression , e esse array é um argumento sendo passado para Select-Object . Ou seja, é o argumento -Property . Observe esta linha do doc do SS64:

To add a calculated property to an object, specify a hash table as a value of the -Property parameter. The hash table must include two keys: Name and Expression with the Expression key assigned a script block that will determine the value of the property.

Então tudo isso faz um pouco mais de sentido agora. É apenas Select-Object transformando a entrada, e está reunindo vários atributos "calculados" (determinados pelo bloco de scripts) e um atributo "não calculado" (já presente no objeto de entrada) para o objeto de saída.

Uma pequena nota: acredito que este atributo calculado em particular é um tanto bobo:

@{Name="LastWriteTime";Expression={$_.LastWriteTime}}

Não vejo nenhum motivo para que ele não tenha sido selecionado diretamente como Name .

    
por 20.10.2016 / 00:15