为什么 PowerShell 拆分包含连字符和句点的参数?

Why does PowerShell split arguments containing hyphens and periods?

在 PowerShell 中 window:

PS C:\> echo -abc.def.ghi
-abc
.def.ghi

出于某种原因,连字符和句点的组合导致 Powershell 将参数分成两行。

没有连字符就不会出现:

PS C:\> echo abc.def.ghi
abc.def.ghi

没有句点时也不会发生:

PS C:\> echo -abcdefghi
-abcdefghi

通过实验,我发现我可以用反引号来避免这种行为:

PS C:\> echo `-abc.def.ghi
-abc.def.ghi

但是为什么会出现这种情况?我不理解 PowerShell 语法的哪个基本部分?

我已经反汇编了 Microsoft.PowerShell.Utility 以查看 Write-Output 的代码那里没什么特别的,它只是遍历 InputObject 并将每个传递给当前 WriteObject 实现的方法 ICommandRuntime

我的猜测是,处理文本的分词器试图将任何以 - 开头的内容与声明的参数相匹配。如果做不到这一点,它将作为 -InputObject 中的一项通过管道传递。由于 . 不能成为变量名的一部分,因此不能成为开关名称的一部分,因此它可能会在执行 if 检查之前将其分开,并且当它被证明是参数时它不会加入它用令牌的其余部分备份。因此,您可能发现了一个小错误。

当使用反引号或引号时,它不会犯这个错误,因为它可以标记整个事物。

不过这都是猜测,我和你一样希望看到权威的答案。

编辑

我所说的证据:

PS> echo -NoEnumerate.foo
.foo

仅供参考,我不确定 George 是否试图提及这一点,但 echo 是 PowerShell 中 Write-Output 的别名。

PS C:\temp> Get-Alias echo

CommandType     Name                                               ModuleName                                                                                
-----------     ----                                               ----------                                                                                
Alias           echo -> Write-Output       

在示例 echo -abc.def.ghi 中,解析器将未加引号的连字符视为 parameter/switch 名称的前缀。期间也有特殊的意义。参数不能包含句点,因此解析器将其视为字符串终止符。

作为一个整体 write-output 将其视为一个数组,因此它在位置上与 -InputObject

匹配

(我希望我的断言没有完全错误。)