如何转义 PowerShell 中的特殊字符?

How to escape special characters in PowerShell?

当我的 PowerShell 脚本运行时,它会提示用户输入密码参数。该密码可以包含任意数量的特殊字符,例如 *\~;(%?.:@/ 该密码随后用作 .exe 命令的参数,但由于某些特殊字符未正确转义,该密码通常不正确。

过去的密码示例是 $(?-.?-(。我需要转义的唯一字符是“(”,我将其替换为“`(”以使其起作用。但是,该密码现在是已过期。新密码类似于 *\~;~(%?.:@/ *注意:这些密码也混合了随机数字和字母,但已被编辑。

新密码中只有*\~;%:@/ 有没有一种简单的方法可以转义所有字符并按原样接受任何用户输入?如果没有,有人介意帮我转义这些特殊字符吗?


param (
    [Parameter(Mandatory=$true)][string]$password
)

以上代码作为脚本的序言,导致控制台提示用户输入。

Invoke-Expression -Command "<path_to_exe> -install $user $password"

^这是使用该密码参数的命令


我在 Stack Overflow、Reddit 和其他各种编码上尝试了许多其他建议 forums/blogs 和 none 都有效。非常感谢任何帮助!

使用下面将使用您提到的转义前缀转义字符。正常的转义前缀是 \,如下所示。我这样设置是为了让你更容易添加额外的字符来转义或更改转义前缀。

function Set-EscapeCharacters {
    Param(
        [parameter(Mandatory = $true, Position = 0)]
        [String]
        $string
    )
    $string = $string -replace '\*', '`*'
    $string = $string -replace '\', '`\'
    $string = $string -replace '\~', '`~'
    $string = $string -replace '\;', '`;'
    $string = $string -replace '\(', '`('
    $string = $string -replace '\%', '`%'
    $string = $string -replace '\?', '`?'
    $string = $string -replace '\.', '`.'
    $string = $string -replace '\:', '`:'
    $string = $string -replace '\@', '`@'
    $string = $string -replace '\/', '`/'
    $string
}

$Password = Set-EscapeCharacters $Password

您正在使用 Invoke-Expression 调用外部程序:

  • 没有这样做的理由,而且Invoke-Expression should generally be avoided:它会导致引用令人头疼(因为在您的情况下),但更重要的是,它可能存在安全风险,通常有更好的解决方案。

    • 顺便说一句:不幸的是,即使直接调用,围绕空字符串参数和带有 embedded " 字符的参数也可能存在引用挑战。 - 见脚注 [1] 和 .
  • 如果您改为直接调用外部程序 - 与任何 shell 一样,包括 PowerShell 是旨在做到 - 您的问题可能会消失:[1]

& <path_to_exe> -install $user $password

注意:&,PowerShell 的 call operator,仅当您的可执行文件的路径被引用(例如,"C:\Program Files\foo.exe")时才需要 and/or 通过 [=56] 指定=]变量引用(例如,$HOME\foo.exe);否则,您可以按原样调用可执行文件(例如,调用 cmd.exe,使用类似
cmd /c 'echo hi')的东西。


另外,如果您发现自己需要转义 字符集 中的任何字符,请使用 -replacecharacter class, [...]:

注意:这不是传递参数所必需的,既不是如上所示的外部程序,也不是PowerShell命令;但是,由于 PowerShell 对传递给 外部程序 的参数值中嵌入的 " 个字符的处理不正确,您可能必须转义 " 个字符(仅),因为 \"[1].

PS> 'a*b\c~d;e(f%g?h.i:j@k/l' -replace '[*\~;(%?.:@/]', '`$&'
a`*b`\c`~d`;e`(f`%g`?h`.i`:j`@k`/l  # all chars. inside [...] were `-escaped

注意:由于 \ 即使在字符 class 中也有特殊含义,因此必须将其转义为 \ - 所有其他字符。按原样使用。

有关 -replace 运算符的详细信息,请参阅


[1] 还有 一个 字符仍然会导致问题:嵌入 "。由于历史原因,PowerShell 不能 正确地将嵌入的 " 正确传递给 外部程序,并且烦人地需要 手动 \-escaping - 详见this GitHub issue。 应用于您的解决方案:& <path_to_exe> -install $user ($password -replace '"', '\"')