PowerShell - Passe FilterScript para Where-Object como variável

Sep 11 2020

Estou tentando obter um bloco de script Where-Object FilterScript em uma variável, mas não tive sorte até agora. Como um exemplo simples do que estou tentando fazer:

$test = @('one','two','three') $filter = '$_ -eq "one"' $test | Where-Object -FilterScript { $filter }

Isso não parece funcionar; Eu recebo de volta todos os elementos. Eu também tentei:

$filter = { $_ -eq "one" } $filter = [scriptblock]::Create($_ -eq 'one')

Todos estes retornam:

one
two
three

No entanto, substituir a variável pelo filtro real funciona conforme o esperado:

$test | Where-Object -FilterScript { $_ -eq "one" }

Isso retorna apenas "um", sem "dois" e "três". Alguém sabe como posso fazer isso funcionar? Eu estava testando originalmente no Core v7.0.3, mas testei no Windows PowerShell v5.1 também.

Respostas

4 Garrett Sep 11 2020 at 15:41

As chaves depois -FilterScriptestão bagunçando você, uma vez que a variável contém um ScriptBlock, você não precisa mais dessas chaves. Se você os tiver lá, é um scriptblock de uma variável contendo um scriptblock.

$foo = "hi" $foo | gm     (TypeName: String)
{$foo} | gm   (TypeName: ScriptBlock)

Se você adicionar [scriptblock]à sua $filtervariável para digitar fortemente a variável, ele reclamará da formatação até que você adicione as chaves ao definir sua variável. Esta é uma ótima maneira de garantir que o objeto que você está alimentando Where-Objectcorresponda ao tipo esperado para seu -FilterScriptparâmetro, que éScriptBlock

Ele funcionará sem que o tipo forte seja forçado uma vez que as chaves estão na definição de variável, o que faz com que se torne um ScriptBlock, mas eu deixaria o tipo lá para que o mecanismo reclamasse se alguém remover as chaves e não perceber estamos mudando seu tipo de variável no processo.

$test = @('one','two','three') [scriptblock]$filter = { $_ -eq "one" } $test | Where-Object -FilterScript $filter
one