为什么powershell自动补全使用单引号并转义特殊字符?
因为 `-escaping 不是 string-interpolation 转义(仅适用于 "..." 字符串),它是 wildcard-pattern 元字符的转义,恰好使用相同转义字符作为字符串插值转义,`.
换句话说:按照设计,` 字符。 保留作为逐字的'...'字符串的一部分,稍后在通配符模式处理期间进行解释。
请参阅下面的“背景信息”部分,其中讨论了 PowerShell 的选项卡补全何时假定文件名参数不仅仅是文字名称而是通配符模式,就像这里的情况一样。
处理此类参数的正确方法是什么?
要防止转义,请确保脚本的(第一个位置)参数命名为
-LiteralPath(参数变量名$LiteralPath)。
一个函数的快速演示:
# Tab-completing an argument that binds to a -LiteralPath parameter deactivates
# escaping.
function foo { param($LiteralPath) $LiteralPath }; foo .\file[bla].dot
这个要求很不幸,因为名称 -LiteralPath 并不总是合适的 - 不幸的是,将不同的名称与 [Alias('LiteralPath') 属性结合使用不起作用。
如果您需要使用不同的参数名称,您可以通过@滚动自己的未转义文件名选项卡完成 987654323@属性:
function foo {
param(
[ArgumentCompleter({
param($unused1, $unused2, $wordToComplete)
(Get-Item ('{0}*' -f ($wordToComplete -replace '[][]', '``$&'))).Name
})]
$SomeParam
)
$SomeParam # echo for diagnostic purposes
}
foo .\file[bla].dot
注意:
替代方法是不尝试修复制表符补全行为,而是unescape收到的参数 ,即使参数 没有 转义,它也应该起作用:
function foo { param($SomeParam) [WildcardPattern]::Unescape($SomeParam) }
# The escaped path is now unescaped inside the function.
foo '.\file`[bla`].dot'
注意:万一您的文件名包含 literal `[ 和 `] 序列并且用户键入或粘贴这样的字面上的名字,该方法会发生故障。事实上,从 v7.1.0 开始,在这种情况下,即使是带有转义的制表符完成也会失败;例如逐字的`[ 变成转义的``[,即使它应该是```[
警告:
- 如果您确实使用包含
[ 和] 的文件路径未转义,则必须确保使用-LiteralPath 参数 稍后将这些路径传递给文件处理 cmdlet,例如 Get-Item、Get-ChildItem 或 Get-Content。
背景信息:
对于除-LiteralPath 以外的任何参数名称,尤其是-Path,PowerShell 假定该参数旨在接受wildcard expressions,因此转义通配符元字符以` 出现在文件名中逐字;因为* 和? 不能是文件名的一部分(至少在Windows 上),这实际上适用于[ 和]。
注意` 在这种情况下不是 字符串插值 转义字符:假设逐字单个引用的字符串( '...') 用于补全,` 字符被保留。但是,如果您在需要 通配符表达式 的上下文中使用这样的字符串,那么通配符引擎会将 ` 识别为 its 转义字符。
相反,这意味着如果您使用expandable(插值)双-引号字符串("..."),则必须使用`` 转义通配符元字符 - 和制表符补全如果你以"开始你的论点,确实会这样做
从 v7.1 开始,PowerShell 与文件名相关的制表符补全行为有点令人遗憾:
对于其类型未隐含完成行为的任何参数(例如,[enum] 派生类型)或没有自定义完成的任何参数执行 file-name 完成是合理的默认行为指定逻辑(例如通过[ArgumentCompleterAttribute()] 或[ValidateSet()] 属性)。
但是: