Как & ldquo; псевдоним & rdquo; со связанным параметром, не нарушая конвейерную обработку в Powershell?

2
задан scobi 19 January 2019 в 08:51
поделиться

2 ответа

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

0
ответ дан Leon Evans 19 January 2019 в 08:51
поделиться

Я нашел этот источник https://blogs.technet.microsoft.com/heyscriptingguy/2011/03/01/proxy-functions-spice-up-your-powershell-core-cmdlets/ [ 119]

В этом случае ярлык / псевдоним для Select-String -First 10 сводится к следующему:

$metadata = New-Object System.Management.Automation.CommandMetaData (Get-Command Select-Object)
[System.Management.Automation.ProxyCommand]::Create($MetaData) | Out-File -FilePath prxyfunctions.psm1

Откройте файл модуля prxyfunctions.psm1 и оберните все содержимое в новый функция называется S10

function S10 {
    [CmdletBinding(DefaultParameterSetName = 'DefaultParameter', HelpUri = 'https://go.microsoft.com/fwlink/?LinkID=113387', RemotingCapability = 'None')]
    param(

    <abbreviated...>

.ForwardHelpTargetName Microsoft.PowerShell.Utility\Select-Object
.ForwardHelpCategory Cmdlet

#>
}

Затем в разделе Begin {} добавьте одно утверждение $PSBoundParameters.Add('First','10'), как показано ниже.

begin {
        try {
            $outBuffer = $null
            if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer)) {
                $PSBoundParameters['OutBuffer'] = 1
            }
            $PSBoundParameters.Add('First','10')
            $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Microsoft.PowerShell.Utility\Select-Object', [System.Management.Automation.CommandTypes]::Cmdlet)
            $scriptCmd = {& $wrappedCmd @PSBoundParameters }
            $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
            $steppablePipeline.Begin($PSCmdlet)
        }
        catch {
            throw
        }
    }

Вот и все. Сохраните файл, импортируйте модуль, введите короткую команду типа gci c:\|s10 и получите всего 10 результатов. Если вы действительно хотите, чтобы все было надежно, нужно больше кодирования. Если используется S10 -First 2, вы получите хорошую ошибку.


РЕДАКТИРОВАТЬ в ответ на полезные комментарии @PetSerAl

Некоторые дальнейшие командлеты в конвейере могут быть не в состоянии обрабатывать функцию прокси, например Sort-Object. Сравните выходные данные этих двух строк

-join (20..1 | Select -First 10 | Sort)
11121314151617181920

-join (20..1 | S10 | Sort)
<nothing>

-join (20..1 | S10 -Wait | Sort)
11121314151617181920

Это можно обойти, используя параметр -Wait в командной строке. Или закодируйте параметр Wait в прокси-функции $PSBoundParameters.Add('Wait',$true)

При работе с большими коллекциями это вызывает сожаление, поскольку отключает функцию Select-Object, которая останавливает конвейер после элементов x, что приводит к большей обработке и более длительному ожиданию.

0
ответ дан Gert Jan Kraaijeveld 19 January 2019 в 08:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: