Как контролировать область действия скриптового блока PowerShell

У меня есть функция, написанная в PowerShell:

function replace([string] $name,[scriptblock] $action) {
    Write-Host "Replacing $name"
    $_ = $name
    $action.Invoke()
}

и будет использоваться как:

$name = "tick"
replace $agentPath\conf\buildAgent.dist.properties {
    (cat templates\buildAgent.dist.properties.tpl) `
        -replace '@@serverurl@@', 'http:/localhost:8080/teamcity' `
        -replace '@@name@@', $name `
        > $_
}

Однако я обнаружил, что в блоке скриптов переменная $name перезаписывается $name параметр изнутри replace функция.

Есть ли способ выполнить блок скрипта, чтобы только переменная $_ добавляется в область действия скриптового блока, но больше ничего нет?

2 ответа

Я предварил свой ответ, утверждая, что powershell только для садистов. Хитрость в том, что если вы поместите функцию в модуль, локальные переменные станут приватными и не будут переданы в блок скрипта. Затем перейти в $_ Переменная вы должны прыгать еще несколько обручей.

gv '_' получить переменную powershell $_ и передает его в контекст через InvokeWithContext,

Теперь я знаю больше, чем когда-либо хотел:|

New-Module {
    function replace([string] $name,[scriptblock] $action) {
        Write-Host "Replacing $name"
        $_ = $name
        $action.InvokeWithContext(@{}, (gv '_'))
    }
}

и как прежде

$name = "tick"
replace $agentPath\conf\buildAgent.dist.properties {
    (cat templates\buildAgent.dist.properties.tpl) `
        -replace '@@serverurl@@', 'http:/localhost:8080/teamcity' `
        -replace '@@name@@', $name `
        > $_
}

Вы могли бы использовать $global: префикс для $name переменная в вашем скрипте:

$name = "tick"
replace $agentPath\conf\buildAgent.dist.properties {
    (cat templates\buildAgent.dist.properties.tpl) `
        -replace '@@serverurl@@', 'http:/localhost:8080/teamcity' `
        -replace '@@name@@', $global:name `
        > $_
}
Другие вопросы по тегам