为什么 PowerShell 在批处理脚本调用时会以空格分割参数以及如何修复它?

Neo*_*nit 3 powershell

非常简单的设置,请在家尝试一下。

测试.ps1

$args
Run Code Online (Sandbox Code Playgroud)

test.rb(如有必要,替换为选择的语言)

$args
Run Code Online (Sandbox Code Playgroud)

测试.bat

@echo off
ruby test.rb "foo bar moo"
powershell .\test.ps1 "foo bar moo"
pause
Run Code Online (Sandbox Code Playgroud)

运行测试.bat。猜猜输出。

如果你像我一样想那你就错了。

输出

["foo bar moo"]
foo
bar
moo
Run Code Online (Sandbox Code Playgroud)

Ruby 见证了这三个单词作为单个参数传递。PowerShell 以比尔·盖茨的名义在做什么?我怎样才能让它按逻辑工作?

或者我错过了什么?

mkl*_*nt0 5

为了使用参数调用脚本文件(.ps1 ) ,请使用PowerShell CLI-File参数,而不是(隐含的)-Command参数:

powershell -File .\test.ps1 "foo bar moo"
Run Code Online (Sandbox Code Playgroud)

请注意,PowerShell(核心)pwsh以 v6 开头的 PowerShell 版本)现在默认-File. [1]


至于你尝试过的

powershell .\test.ps1 "foo bar moo"
Run Code Online (Sandbox Code Playgroud)

-c隐式地与(您也可以使用代替)相同-Command

powershell -Command .\test.ps1 "foo bar moo"
Run Code Online (Sandbox Code Playgroud)

这会导致 PowerShell 分两个阶段评估参数:

  • 首先,剥离"各个参数的语法,然后将生成的参数与空格连接以形成单个字符串。

  • 其次,生成的字符串(.\test.ps1 foo bar moo在本例中)随后被解释为 PowerShell 源代码,并且如您所见,原始字符串"此时已被剥离,导致脚本接收3 个参数。

笔记:

  • -Command因此,与 不同, 的行为还涉及根据PowerShell的规则对参数进行额外的解释-File。例如,
    powershell -File .\test.ps1 $HOME$HOME 逐字传递给脚本,而
    powershell -Command .\test.ps1 $HOME将传递PowerShell 自动变量的值$HOME

  • 使用-Command,传递"将成为正在评估的结果 PowerShell 代码一部分的字符确实需要转义

    • 从 PowerShell 的角度来看,最强大的形式是\"(原文如此),尽管从批处理文件调用时可能会导致命令行损坏/cmd.exe
    • 如果出现问题,请传递包含在"..."to中的单个参数,并像Windows PowerShell 中的PowerShell (Core) / as (sic) 中那样-Command转义传递。""""^""
  • 有关何时使用vs. 的更多指导,请参阅此答案-File-Command


[1] 考虑到大多数 shell 和脚本引擎 CLI 需要显式参数(通常为 或)来传递命令字符串而不是脚本文件路径,因此期望-File, 不是-Command默认参数是可以理解的。幸运的是,在 PowerShell (Core) 7+ 中,现在默认设置,这是支持 Unix 上的 shebang 行所必需的更改。 此外,大多数 shell 和脚本引擎 CLI 都希望命令字符串作为单个参数传递,任何其他参数都会成为传递给命令字符串中代码的参数,而 PowerShell 只是将多个参数拼接在一起,然后将结果解释为命令字符串;请参阅GitHub 问题 #4024-c-e-File