问题
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 andgrepsls'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 theGet-
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