PowerShell - передать FilterScript в Where-Object как переменную

Sep 11 2020

Я пытаюсь поместить блок сценария Where-Object FilterScript в переменную, но мне не очень повезло. В качестве простого примера того, что я пытаюсь сделать:

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

Похоже, это не работает; Возвращаю все элементы. Я также пробовал:

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

Все они возвращаются:

one
two
three

Однако замена переменной фактическим фильтром работает должным образом:

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

Это возвращает только «один», без «два» и «три». Кто-нибудь знает, как я могу заставить это работать? Изначально я пробовал его на Core v7.0.3, но тестировал и на Windows PowerShell v5.1.

Ответы

4 Garrett Sep 11 2020 at 15:41

Фигурные скобки после -FilterScriptних мешают вам, поскольку, если переменная содержит ScriptBlock, вам больше не нужны эти фигурные скобки. Если они у вас там есть, то это блок сценария переменной, содержащий блок сценария.

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

Если добавить [scriptblock]к вашей $filterпеременной сильно ввести переменную, он жалуется на форматирование , пока вы не добавите скобки , когда вы определяете переменную. Это отличный способ убедиться, что объект, который вы кормите, Where-Objectсоответствует ожидаемому типу для его -FilterScriptпараметра, которыйScriptBlock

Он будет работать без принудительного использования строгого типа, когда фигурные скобки находятся в определении переменной, что приводит к тому, что он становится ScriptBlock, но я бы оставил тип там, поэтому движок жалуется, если кто-то удаляет фигурные скобки и не понимает, что они меняем тип вашей переменной в процессе.

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