Функция не получает привязки при использовании в модуле

Я пытаюсь поставить эту функцию:

function Test-Any {
    [CmdletBinding()]
    param($EvaluateCondition,
        [Parameter(ValueFromPipeline = $true)] $ObjectToTest)
    begin {
        $any = $false
    }
    process {
        if (-not $any -and (& $EvaluateCondition $ObjectToTest)) {
            $any = $true
        }
    }
    end {
        $any
    }
}

в модуль. Я только что создал новый модуль, файл my-scripts.psm1, который содержит только указанную выше функцию, и импортирую его с помощью Import-Module <absolute path>.

Проблема в том, что если я использую функцию из модуля, 1..4 | Test-Any { $_ -gt 3 } возвращает false, потому что для $_ не задано значение из канала.

Если я обычно определяю функцию в сценарии и использую ее оттуда, она работает должным образом (при этом $ _ получает целочисленные значения).

Это происходит с PowerShell v4.0 под Windows 7.


person Voo    schedule 20.10.2015    source источник
comment
Благодаря помощи @ PetSerAl, теперь в моем ответе выходит из конвейера, как только успешно завершится тест) версия этой функции.   -  person mklement0    schedule 17.01.2016


Ответы (1)


Эта команда: & $EvaluateCondition $ObjectToTest - ничего не связывает с $_. При отсутствии блока param() в ScriptBlock значение $ObjectToTest будет привязано к $args[0].

$SB = {"`$_: '$_'; `$args[0]:'$($args[0])'"}
1..3 | ForEach-Object {& $SB ($_+3)}

Вывод:

$_: '1'; $args[0]:'4'
$_: '2'; $args[0]:'5'
$_: '3'; $args[0]:'6'

Почему ссылка на $_ работает: вы просто ссылаетесь на переменную $_ из родительской области.

Значение $_, которое вы видите, является текущим входным объектом конвейера, переданным в функцию Test-Any.

function Test-Any {
    param($EvaluateCondition)
    process {
        "Test-Any `$_: '$_'"
        & $EvaluateCondition
    }
}
1..2 | %{3..4 | Test-Any {"EvaluateCondition `$_:'$_'"}}

Вывод:

Test-Any $_: '3'
EvaluateCondition $_:'3'
Test-Any $_: '4'
EvaluateCondition $_:'4'
Test-Any $_: '3'
EvaluateCondition $_:'3'
Test-Any $_: '4'
EvaluateCondition $_:'4'

Когда вы определяете Test-Any в области модуля, тогда переменная $_ с конвейерным вводом в Test-Any также была определена в этой области модуля и была недоступна за ее пределами.

New-Module {
    function Test-Any {
        param($EvaluateCondition)
        process {
            "Test-Any `$_: '$_'"
            & $EvaluateCondition
        }
    }
} | Out-Null
1..2 | %{3..4 | Test-Any {"EvaluateCondition `$_:'$_'"}}

Вывод:

Test-Any $_: '3'
EvaluateCondition $_:'1'
Test-Any $_: '4'
EvaluateCondition $_:'1'
Test-Any $_: '3'
EvaluateCondition $_:'2'
Test-Any $_: '4'
EvaluateCondition $_:'2'

Если вы хотите вызвать блок скрипта с некоторым значением, привязанным к $_, то один из способов сделать это:

ForEach-Object $EvaluateCondition -InputObject $ObjectToTest
person user4003407    schedule 20.10.2015