美文网首页
powershell 脚本中参数自动补全的4种实现方法

powershell 脚本中参数自动补全的4种实现方法

作者: mudssky | 来源:发表于2023-06-29 17:04 被阅读0次

    powershell的脚本可以支持参数自动补全,这样我们在命令行输入对应的参数的时候,就可以按tab键选择。

    提供参数补全的脚本会更容易使用,不用用户输入比较方便,而且避免用户输入出错的问题。

    01.ValidateSet属性

    这个属性为参数和变量指定一组值,提供参数校验和tab补全。

    如果参数和Set种的值不匹配,就会Error报错。

    使用方法如下

    Param(
        [Parameter(Mandatory=$true)]
        [ValidateSet('Apple', 'Banana', 'Pear')]
        [string[]]
        $Fruit
    )
    

    使用类的动态ValidateSet

    Class SoundNames : System.Management.Automation.IValidateSetValuesGenerator {
        [string[]] GetValidValues() {
            $SoundPaths = '/System/Library/Sounds/',
                          '/Library/Sounds',
                          '~/Library/Sounds'
            $SoundNames = ForEach ($SoundPath in $SoundPaths) {
                If (Test-Path $SoundPath) {
                    (Get-ChildItem $SoundPath).BaseName
                }
            }
            return [string[]] $SoundNames
        }
    }
    
    Param(
        [ValidateSet([SoundNames])]
        [string]$Sound
    )
    

    IValidateSetValuesGenerator 是在 PowerShell 6.0 中引入的。

    02.ArgumentCompletions

    和ValidateSet类似,但是只是提供补全,没有校验,也是powershell6.0引入

    function Test-ArgumentCompletions {
        [CmdletBinding()]
        param (
            [Parameter(Mandatory=$true)]
            [ArgumentCompletions('Fruits', 'Vegetables')]
            $Type,
    
            [Parameter()]
            [ArgumentCompletions('Apple', 'Banana', 'Orange')]
            $Fruit,
    
            [Parameter()]
            [ArgumentCompletions('Onion', 'Carrot', 'Lettuce')]
            $Vegetable
        )
    }
    

    03.ArgumentCompleter

    和ArgumentCompletions 类似,但是支持脚本块,也就是可以动态获取参数

    function MyArgumentCompleter {
        Param(
            [Parameter(Mandatory)]
            [ArgumentCompleter( {
                param ( $commandName,
                        $parameterName,
                        $wordToComplete,
                        $commandAst,
                        $fakeBoundParameters )
                # Perform calculation of tab completed values here.
            } )]
            $ParamName
        )
    }
    

    下面是一个例子

    function MyArgumentCompleter{
        param ( $commandName,
                $parameterName,
                $wordToComplete,
                $commandAst,
                $fakeBoundParameters )
    
        $possibleValues = @{
            Fruits = @('Apple', 'Orange', 'Banana')
            Vegetables = @('Onion', 'Carrot', 'Lettuce')
        }
    
        if ($fakeBoundParameters.ContainsKey('Type')) {
            $possibleValues[$fakeBoundParameters.Type] | Where-Object {
                $_ -like "$wordToComplete*"
            }
        } else {
            $possibleValues.Values | ForEach-Object {$_}
        }
    }
    
    function Test-ArgumentCompleter {
    [CmdletBinding()]
     param (
            [Parameter(Mandatory=$true)]
            [ValidateSet('Fruits', 'Vegetables')]
            $Type,
    
            [Parameter(Mandatory=$true)]
            [ArgumentCompleter({ MyArgumentCompleter @args })]
            $Value
          )
    }
    

    04.基于类的自动完成

    powershell7.2引入

    可以创建可重复泛用的泛型完成器,比如

    [DirectoryCompleter(ContainingFile="pswh.exe", Depth=2)]
    
    [DateCompleter(WeekDay='Monday', From="LastYear")]
    
    [GitCommits(Branch='release')]
    

    感觉和写C#差不多了。

    using namespace System.Collections
    using namespace System.Collections.Generic
    using namespace System.Management.Automation
    using namespace System.Management.Automation.Language
    
    class NumberCompleter : IArgumentCompleter {
    
        [int] $From
        [int] $To
        [int] $Step
    
        NumberCompleter([int] $from, [int] $to, [int] $step) {
            if ($from -gt $to) {
                throw [ArgumentOutOfRangeException]::new("from")
            }
            $this.From = $from
            $this.To = $to
            $this.Step = $step -lt 1 ? 1 : $step
        }
    
        [IEnumerable[CompletionResult]] CompleteArgument(
            [string] $CommandName,
            [string] $parameterName,
            [string] $wordToComplete,
            [CommandAst] $commandAst,
            [IDictionary] $fakeBoundParameters) {
    
            $resultList = [List[CompletionResult]]::new()
            $local:to = $this.To
            $local:step = $this.Step
            for ($i = $this.From; $i -lt $to; $i += $step) {
                $resultList.Add([CompletionResult]::new($i.ToString()))
            }
    
            return $resultList
        }
    }
    
    class NumberCompletionsAttribute : ArgumentCompleterAttribute, IArgumentCompleterFactory {
        [int] $From
        [int] $To
        [int] $Step
    
        NumberCompletionsAttribute([int] $from, [int] $to, [int] $step) {
            $this.From = $from
            $this.To = $to
            $this.Step = $step
        }
    
        [IArgumentCompleter] Create() { return [NumberCompleter]::new($this.From, $this.To, $this.Step) }
    }
    
    function Add{
        param(
           [NumberCompletions(0, 100, 5)]
           [int] $X,
    
           [NumberCompletions(0, 100, 5)]
           [int] $Y
        )
        $X + $Y
    }
    

    总结

    一般还是用ValidateSet,

    复杂一点就用ArgumentCompleter结合脚本块实现。

    在powershell中用class就感觉很不方便。。。

    相关文章

      网友评论

          本文标题:powershell 脚本中参数自动补全的4种实现方法

          本文链接:https://www.haomeiwen.com/subject/zmxzydtx.html