我的PowerShell引号为什么不能正确地转义?

3
我想将一个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的新手,尝试了其他答案中的建议,但都无法使其正常工作(失败原因各种各样)。


你尝试过在外部使用 " 并在内部使用 ',以避免需要转义 " 吗? - sodawillow
@sodawillow 我尝试了相反的方法,但似乎那样行得通。谢谢。 - Dov
3个回答

4
据我所知,您的转义没有问题,但是您误解了 Invoke-Expression 的工作原理。该 cmdlet 提供了一种将给定字符串作为命令行运行的方式。但是,PowerShell 不接受裸字符串(在您的情况下为 "C:\Program Files\Git\bin\git.exe")作为命令行中的命令,除非您使用 调用运算符&)。否则,它将尝试回显该字符串,但由于出现意外标记而失败:

演示:

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个字节的数据对127.0.0.1进行Ping操作: 来自127.0.0.1的回复: 字节=32 时间<1ms TTL=128
127.0.0.1的Ping统计信息: 数据包: 已发送 = 1,已接收 = 1,丢失 = 0 (0% 丢失), 往返行程的估计时间(以毫秒为单位): 最短 = 0ms,最长 = 0ms,平均 = 0ms
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:\> Invoke-Expression $cmd
Invoke-Expression:在第1行第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个字符处
+ Invoke-Expression $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:\> Invoke-Expression $cmd Ping 127.0.0.1 的回复: 数据包: 已发送 = 1,已接收 = 1,丢失 = 0 (0% 丢失), 往返行程的估计时间(以毫秒为单位): 最短 = 0ms,最长 = 0ms,平均 = 0ms

这意味着您可以直接使用调用运算符,完全放弃Invoke-Expression(正如@MartinBrandl所建议的那样)。

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

一如既往,好答案。 - Martin Brandl

3
首先,我会使用 Join-Path 命令将路径组合起来,然后使用 & 调用 git 并传递参数:
$gitExe = Join-Path $env:programfiles '\Git\bin\git.exe'
& $gitExe -c $solutionFolder

$gitExe 变量之后还有其他操作。例如:$gitExe add -f $theFile - Dov
1
如果可能的话,您应该将所有参数保存在哈希表中,并使用splatting将其传递给$gitExe - Martin Brandl

1
在双引号内使用单引号:
$gitExe = "'$env:programfiles\Git\bin\git.exe' -C '$solutionFolder'"

相反,变量将不会被展开。

1
这与Invoke-Expression结合使用无效。 - Ansgar Wiechers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接