PowerShell: pase FilterScript a Where-Object como variable

Sep 11 2020

Estoy tratando de obtener un bloque de script Where-Object FilterScript en una variable, pero no he tenido suerte hasta ahora. Como ejemplo simple de lo que estoy tratando de hacer:

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

Esto no parece funcionar; Recupero todos los elementos. También probé:

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

Todos estos regresan:

one
two
three

Sin embargo, reemplazar la variable con el filtro real funciona como se esperaba:

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

Esto devuelve solo "uno", sin "dos" y "tres". ¿Alguien sabe cómo puedo hacer que esto funcione? Originalmente lo estaba probando en Core v7.0.3, pero también lo probé en Windows PowerShell v5.1.

Respuestas

4 Garrett Sep 11 2020 at 15:41

Las llaves posteriores te -FilterScriptestán arruinando, una vez que la variable contiene un ScriptBlock, ya no necesitas esas llaves. Si los tiene ahí, es un scriptblock de una variable que contiene un scriptblock.

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

Si agrega [scriptblock]a su $filtervariable para escribir fuertemente la variable, se queja del formato hasta que agrega las llaves cuando define su variable. Esta es una excelente manera de asegurarse de que el objeto que está alimentando Where-Objectcoincida con el tipo esperado para su -FilterScriptparámetro, que esScriptBlock

Funcionará sin que se fuerce el tipo fuerte una vez que las llaves están en la definición de variable, lo que hace que se convierta en un ScriptBlock, pero dejaría el tipo allí para que el motor se queje si alguien quita las llaves y no se da cuenta está cambiando su tipo de variable en el proceso.

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