【问题标题】:Why aren't my PowerShell quotes escaping properly为什么我的 PowerShell 引号不能正确转义
【发布时间】:2016-10-27 12:40:43
【问题描述】:

我正在尝试将 PowerShell 变量分配给我想在其他地方调用的命令的一部分(Git 命令)。我有这一行:

$gitExe = "`"$env:programfiles\Git\bin\git.exe`" -C `"$solutionFolder`""

我期望产生这样的值:

"C:\Program Files\Git\bin\git.exe" -C "C:\MySolution"

相反,当脚本运行时(作为 Visual Studio 2015 中 NuGet 包安装的一部分)我收到此错误:

Invoke-Expression : At line:1 char:3
+ ""C:\Program Files (x86)"\Git\bin\git.exe -C "C:\MySolution ...
+   ~~~~~~~~~~
Unexpected token 'C:\Program' in expression or statement.

我是 PowerShell 新手,虽然我尝试了其他答案的建议,但我无法让它工作(有各种不同的失败)。

【问题讨论】:

  • 你有没有尝试在外面使用"s,在里面使用's,以避免不得不逃避"s?
  • @sodawillow 我尝试了相反的方法,但看起来它有效。谢谢

标签: visual-studio powershell nuget


【解决方案1】:

AFAICS 你的逃跑没有错,但你误解了Invoke-Expression 的工作原理。 cmdlet 提供了一种将给定字符串作为命令行运行的方法。但是,PowerShell 不接受裸字符串(在您的情况下为 "C:\Program Files\Git\bin\git.exe")作为命令行中的命令,除非您使用 call operator (&)。相反,它会尝试回显字符串,但由于意外令牌而失败:

演示:

PS C:\> "$env:windir\system32\ping.exe"
C:\Windows\system32\ping.exe
PS C:\> "$env:windir\system32\ping.exe" -n 1 127.0.0.1
在行:1 字符:33
+ "$env:windir\System32\PING.EXE" -n 1 127.0.0.1
+ ~~
表达式或语句中出现意外的标记“-n”。
在行:1 字符:36
+ "$env:windir\System32\PING.EXE" -n 1 127.0.0.1
+ ~
表达式或语句中出现意外的标记“1”。
在行:1 字符:38
+ "$env:windir\System32\PING.EXE" -n 1 127.0.0.1
+~~~~~~~~~
表达式或语句中出现意外的标记“127.0.0.1”。
    + CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : UnexpectedToken

PS C:\> & "$env:windir\system32\ping.exe" -n 1 127.0.0.1

用 32 个字节的数据 ping 127.0.0.1:
来自 127.0.0.1 的回复:bytes=32 time

PS C:\> $cmd = "'$env:windir\system32\ping.exe' -n 1 127.0.0.1"
PS C:\> $cmd
'C:\Windows\system32\ping.exe' -n 1 127.0.0.1
PS C:\> 调用表达式 $cmd
调用表达式:在 line:1 char:32
+ 'C:\Windows\system32\ping.exe' -n 1 127.0.0.1
+ ~~
表达式或语句中出现意外的标记“-n”。
在行:1 字符:35
+ 'C:\Windows\system32\ping.exe' -n 1 127.0.0.1
+ ~
表达式或语句中出现意外的标记“1”。
在行:1 字符:37
+ 'C:\Windows\system32\ping.exe' -n 1 127.0.0.1
+~~~~~~~~~
表达式或语句中出现意外的标记“127.0.0.1”。
在行:1 字符:1
+ 调用表达式 $cmd
+ ~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : ParserError: (:) [Invoke-Expression], ParseException
    + FullyQualifiedErrorId : UnexpectedToken,Microsoft.PowerShell.Commands.InvokeExpressionCommand

PS C:\> $cmd = "& '$env:windir\system32\ping.exe' -n 1 127.0.0.1"
PS C:\> $cmd
& 'C:\Windows\system32\ping.exe' -n 1 127.0.0.1
PS C:\> 调用表达式 $cmd

用 32 个字节的数据 ping 127.0.0.1:
来自 127.0.0.1 的回复:bytes=32 time

这意味着您也可以立即使用呼叫操作员并完全放弃Invoke-Expression(正如@MartinBrandl 已经建议的那样)。

$gitExe = "$env:ProgramFiles\Git\bin\git.exe"
& $gitExe -c $solutionFolder

【讨论】:

  • 一如既往,很好的答案。
【解决方案2】:

首先,我将使用Join-Path cmdlet 组合路径,然后使用& 调用git 并传递参数:

$gitExe = Join-Path $env:programfiles '\Git\bin\git.exe'
& $gitExe -c $solutionFolder

【讨论】:

  • $gitExe 变量后面还有其他东西。例如:$gitExe add -f $theFile
  • 那么您可能应该将所有参数保存在哈希表中并使用 splatting 将其传递给$gitExe
【解决方案3】:

在双引号内使用单引号:

$gitExe = "'$env:programfiles\Git\bin\git.exe' -C '$solutionFolder'"

反之,变量不会被扩展。

【讨论】:

  • 不能与Invoke-Expression结合使用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多