Script Argument matching

这一生的挚爱 提交于 2021-01-27 07:14:57

问题


Does PowerShell do some sort of nearest match or autocompletion when dealing with arguments passed to a script? Given this code...

[CmdletBinding()]
Param(
    [string][Alias("aS")] $applySet,
    [string][Alias("cS")] $conformSet,

    [string][Alias("sL")] $setList,
    [Parameter(ValueFromRemainingArguments = $true)][Object[]]$extraParameters = @()
)

Write-Host "s:  $set"
Write-Host "sL: $setList"
Write-Host "aS: $applySet"
Write-Host "cS: $conformSet"
Write-Host "X:  $extraParameters"

If I use -junk "junk" in the script shortcut I get that info in $extraParameters as expected. Misspelling something, say -aplySet, also shows up as an extra parameter. However, using -set actually populates the $setList variable rather than $extraParameters as I would expect.

Verified in PowerShell 2.0 and 5.1. Any thoughts?


回答1:


PowerShell allows using the initial characters of a parameter name as long as they are unambiguous.




回答2:


It is somewhat undocumented, as far as I can tell.

  • about_Parameters doesn't mention the use of abbreviated parameters.
  • about_Command_Syntax talks about using parameters but not short versions.
  • I Save-Help'd all the help and grep sls'd it for likely terms, couldn't see anything relevant.
  • This blog post from 2006 talks about it, so it has been in PowerShell since version 1.0

In PowerShell 1.0, part of the parameter name resolution logic includes support for identifying parameters by the shortest substring that uniquely identifies the parameter or an alias to the parameter when compared with a list of parameters and aliases for the cmdlet.

and it's mentioned in PowerShell developer Bruce Payette's book 'PowerShell In Action', chapter 2, P.39-40:

The piece of the PowerShell interpreter that figures all of this out is called the parameter binder. The parameter binder is smart - it doesn’t require that you specify the full name of a parameter as long as you specify enough for it to uniquely distinguish what you mean.

But that's it, no comment on design choice or rationale that I can see. Speculating, as @Mike Shepard comments, PowerShell's dual role as an interactive shell (where people want to type as little as possible, and are writing one-off throwaway commands) and a scripting language (where people want clarity, readability, maintainability by multiple people over longer times) is what gives rise to the short form / long form versions of everything.

gci -r | sls (date)
Get-ChildItem -Recurse | Select-String -Pattern (Get-Date)
  • Aliases
  • Positional parameter binding, without the parameter name
  • Parameter name abbreviation
  • Parameter to object property automagic binding
  • Command resolution can lookup Get- cmdlets if the Get- is left out

Fwiw, it appears to be this line in the source code of System.Management.Automation/engine/MergedCommandParameterMetadat.cs, which someone on the PowerShell Slack identified, which actually does the parameter match:

foreach (string parameterName in _bindableParameters.Keys)
{
// ---
    if (CultureInfo.InvariantCulture.CompareInfo.IsPrefix(parameterName, name, CompareOptions.IgnoreCase))
// ---
    {
        // If it is an exact match then only return the exact match
        // as the result

        if (tryExactMatching && String.Equals(parameterName, name, StringComparison.OrdinalIgnoreCase))
        {
            return _bindableParameters[parameterName];
        }
        else
        {
            matchingParameters.Add(_bindableParameters[parameterName]);
        }
    }
}


来源:https://stackoverflow.com/questions/40428613/script-argument-matching

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!