如何在 PowerShell 中转义特殊字符? [英] How to escape special characters in PowerShell?

查看:37
本文介绍了如何在 PowerShell 中转义特殊字符?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

<小时>

参数 ([Parameter(Mandatory=$true)][string]$password)

上面的代码在脚本的前面,导致控制台提示用户输入.

Invoke-Expression -Command " -install $user $password"

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

<小时>

我在 Stack Overflow、Reddit 和其他各种编码论坛/博客上尝试了许多其他建议,但都没有奏效.非常感谢任何帮助!

解决方案

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

  • 没有理由这样做,并且Invoke-Expression 通常应该避免:它会导致引用问题(就像你的情况一样),但是,更重要的是,这可能会带来安全风险,而且通常有更好的解决方案.

    • 顺便说一句:不幸的是,即使使用直接调用,也可能会在空字符串参数和带有 embedded " 字符的参数周围引用挑战. - 参见脚注 [1]和这个答案.
  • 如果您改为直接调用外部程序 - 正如任何外壳程序,包括 PowerShell 旨在执行的那样 - 您的问题可能会消失:[1]

&<path_to_exe>-安装 $user $password

注意:&,PowerShell 的 调用运算符,仅当您的可执行文件的路径被引用时才需要(例如,"C:Program Filesfoo.exe")和/或通过变量引用指定(例如,$HOMEfoo.exe);否则,您可以按原样调用可执行文件(例如,要调用 cmd.exe,请使用诸如
cmd/c 'echo hi' 之类的东西).<小时>

另外,如果您发现自己需要对一组字符中的任何字符进行转义,请使用带有-replace"https://docs.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference#character-classes" rel="nofollow noreferrer">字符类, [...]:

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

PS>'a*bc~d;e(f%g?h.i:j@k/l' -replace '[*\~;(%?.:@/]', '`$&'a`*b`c`~d`;e`(f`%g`?h`.i`:j`@k`/l # [...] 里面的所有字符都被`-escaped

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

有关 -replace 运算符的更多信息,请参阅此答案.

<小时>

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

When my PowerShell script runs, it prompts the user for a password parameter. That password can contain any number of special characters like *~;(%?.:@/ That password is then used as a parameter for a .exe command, but it is often incorrect due to some special characters not being escaped properly.

An example past password was $(?-.?-(. The only characters I needed to escape was '(', which I replaced with '`(' to make it work. However, that password is now expired. The new password is something like *~;~(%?.:@/ *NOTE: these passwords have random numbers and letters mixed into them as well, but have been redacted.

The only characters in the new password NOT in the first are *~;%:@/ Is there an easy way to escape all characters and just take any user input as it is? If not, would someone mind helping me escape these special characters?


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

The above code prefaces the script, causing the console to prompt for user input.

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

^this is the command that uses that password parameter


I have tried many other suggestions on Stack Overflow, Reddit, and other various coding forums/blogs and none have worked. Any help is much appreciated!

解决方案

You're using Invoke-Expression to call an external program:

  • There's no reason to do that, and Invoke-Expression should generally be avoided: it causes quoting headaches (as in your case), but, more importantly, it can be a security risk and there are typically better solutions.

    • As an aside: Unfortunately, even with direct invocation there can be quoting challenges around empty-string arguments and arguments with embedded " chars. - see footnote [1] and this answer.
  • If you instead invoke the external program directly - as any shell, including PowerShell is designed to do - your problem will likely go away:[1]

& <path_to_exe> -install $user $password

Note: &, PowerShell's call operator, is only needed if your executable's path is quoted (e.g, "C:Program Filesfoo.exe") and/or is specified via a variable reference (e.g., $HOMEfoo.exe); otherwise, you can invoke the executable as-is (e.g., to invoke cmd.exe, use something like
cmd /c 'echo hi').


Separately, if you do ever find yourself needing to escape any of the characters in a set of characters, use -replace with a character class, [...]:

Note: This is not necessary for passing arguments, neither to external programs, as shown above, nor to PowerShell commands; however, due to PowerShell's broken handling of " characters embedded in argument values passed to external programs, you may have to escape " characters (only), as "[1].

PS> 'a*bc~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

Note: Since has special meaning even inside a character class, it had to be escaped as \ - all other chars. are used as-is.

For more information about the -replace operator, see this answer.


[1] There is one character that still causes problems: embedded ". For historical reasons, PowerShell does not properly pass embedded " correctly to external programs, and annoyingly requires manual -escaping - see this GitHub issue for details. Applied to your solution:& <path_to_exe> -install $user ($password -replace '"', '"')

这篇关于如何在 PowerShell 中转义特殊字符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆