管道脚本时如何使用多行命令,例如 here-strings?
How to use mutli-line commands such as here-strings when piping a script?
在使用 PowerShell 可执行文件的 -Command -
选项时,我遇到了以下限制:
Write-Host "SETUP"
Set-PSDebug -Trace 2
Write-Host "TEST ONE"
$foo = "BAR"
Write-Host "TEST TWO"
Get-ChildItem
Write-Host "TEST THREE"
$bar = @"
BAZ
"@
Write-Host "DONE"
如果我将之前的内容保存到test.ps1
并执行cat .\test.ps1 | powershell -Command -
,我得到以下输出:
SETUP
DEBUG: 1+ >>>> Write-Host "TEST ONE"
DEBUG: ! CALL function '<ScriptBlock>'
TEST ONE
DEBUG: 1+ >>>> $foo = "BAR"
DEBUG: ! CALL function '<ScriptBlock>'
DEBUG: ! SET $foo = 'BAR'.
DEBUG: 1+ >>>> Write-Host "TEST TWO"
DEBUG: ! CALL function '<ScriptBlock>'
TEST TWO
DEBUG: 1+ >>>> Get-ChildItem
DEBUG: ! CALL function '<ScriptBlock>'
Directory: C:\empty
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 26/02/2017 15:39 179 test.ps1
DEBUG: 1+ >>>> Write-Host "TEST THREE"
DEBUG: ! CALL function '<ScriptBlock>'
TEST THREE
如您所见,Write-Host "DONE"
行的输出从未显示。
因此,在逐行评估时,这里的字符串 似乎发生了一些事情。为什么会这样?
而且,更重要的是,有没有办法让 here strings 在这种情况下工作?
注意:以下适用于 Windows PowerShell v5.1.14393.693 和 PowerShell Core v6.0.0-alpha16。
PetSerAl,正如他经常做的那样,在问题的评论中提供了关键指针(后来,通过评论,也提供了最简单的修复):
It seems that the problem is not with here-strings [per se], but with multiline commands [in general].
-Command -
需要 在 最后一个多行命令[=之后至少有 1 个空行82=] 在输入中正确识别所有命令。
根据定义,here-string 是多行命令的一个实例,这就是您遇到此问题的原因。
因此,要解决包含多行命令的脚本中的问题,请在末尾插入一个空行:
Write-Host "SETUP"
Set-PSDebug -Trace 2
Write-Host "TEST ONE"
$foo = "BAR"
Write-Host "TEST TWO"
Get-ChildItem
Write-Host "TEST THREE"
$bar = @"
BAZ
"@
Write-Host "DONE" # IMPORTANT: Note the empty line below.
为什么这是必要的?
答案可以在 powershell 自己的 CLI 帮助 (powershell -?
) 中找到,其 对 -Command
参数的描述 开头为(重点添加):
Executes the specified commands (and any parameters) as though they were
typed at the Windows PowerShell command prompt
没有加载PSReadLine
模块,当你键入多行命令时交互,你需要一个extra Enter键来提交条目,这样才能让PowerShell 知道您何时输入完命令。
注意:PSReadLine
模块成为 interactive PowerShell 会话的标准部分 W10/PSv5,谢天谢地 避免了这个额外击键的需要,因为它从输入内容的语法推断命令是否完整。
但是,当您通过 -Command -
.
传递命令时,PSReadLine
不涉及
如果你想体验PowerShell本身如何在交互式会话中解析多行命令,请先执行Remove-Module PSReadLine
。
不幸的是,当 -Command -
用于通过 stdin 提供命令时,应用相同的逻辑,所以 你必须模拟额外的 Enter 输入 空行 ,尽管 PetSerAl 发现 [= =47=]单空行最后就够了
如果您希望看到此行为发生变化 and/or 需要对 -File -
的适当支持以将输入视为 脚本 ,请考虑将您的在 GitHub issue #3223.
中听到的声音
在使用 PowerShell 可执行文件的 -Command -
选项时,我遇到了以下限制:
Write-Host "SETUP"
Set-PSDebug -Trace 2
Write-Host "TEST ONE"
$foo = "BAR"
Write-Host "TEST TWO"
Get-ChildItem
Write-Host "TEST THREE"
$bar = @"
BAZ
"@
Write-Host "DONE"
如果我将之前的内容保存到test.ps1
并执行cat .\test.ps1 | powershell -Command -
,我得到以下输出:
SETUP
DEBUG: 1+ >>>> Write-Host "TEST ONE"
DEBUG: ! CALL function '<ScriptBlock>'
TEST ONE
DEBUG: 1+ >>>> $foo = "BAR"
DEBUG: ! CALL function '<ScriptBlock>'
DEBUG: ! SET $foo = 'BAR'.
DEBUG: 1+ >>>> Write-Host "TEST TWO"
DEBUG: ! CALL function '<ScriptBlock>'
TEST TWO
DEBUG: 1+ >>>> Get-ChildItem
DEBUG: ! CALL function '<ScriptBlock>'
Directory: C:\empty
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 26/02/2017 15:39 179 test.ps1
DEBUG: 1+ >>>> Write-Host "TEST THREE"
DEBUG: ! CALL function '<ScriptBlock>'
TEST THREE
如您所见,Write-Host "DONE"
行的输出从未显示。
因此,在逐行评估时,这里的字符串 似乎发生了一些事情。为什么会这样?
而且,更重要的是,有没有办法让 here strings 在这种情况下工作?
注意:以下适用于 Windows PowerShell v5.1.14393.693 和 PowerShell Core v6.0.0-alpha16。
PetSerAl,正如他经常做的那样,在问题的评论中提供了关键指针(后来,通过评论,也提供了最简单的修复):
It seems that the problem is not with here-strings [per se], but with multiline commands [in general].
-Command -
需要 在 最后一个多行命令[=之后至少有 1 个空行82=] 在输入中正确识别所有命令。
根据定义,here-string 是多行命令的一个实例,这就是您遇到此问题的原因。
因此,要解决包含多行命令的脚本中的问题,请在末尾插入一个空行:
Write-Host "SETUP"
Set-PSDebug -Trace 2
Write-Host "TEST ONE"
$foo = "BAR"
Write-Host "TEST TWO"
Get-ChildItem
Write-Host "TEST THREE"
$bar = @"
BAZ
"@
Write-Host "DONE" # IMPORTANT: Note the empty line below.
为什么这是必要的?
答案可以在 powershell 自己的 CLI 帮助 (powershell -?
) 中找到,其 对 -Command
参数的描述 开头为(重点添加):
Executes the specified commands (and any parameters) as though they were typed at the Windows PowerShell command prompt
没有加载PSReadLine
模块,当你键入多行命令时交互,你需要一个extra Enter键来提交条目,这样才能让PowerShell 知道您何时输入完命令。
注意:PSReadLine
模块成为 interactive PowerShell 会话的标准部分 W10/PSv5,谢天谢地 避免了这个额外击键的需要,因为它从输入内容的语法推断命令是否完整。
但是,当您通过 -Command -
.
传递命令时,PSReadLine
不涉及
如果你想体验PowerShell本身如何在交互式会话中解析多行命令,请先执行Remove-Module PSReadLine
。
不幸的是,当 -Command -
用于通过 stdin 提供命令时,应用相同的逻辑,所以 你必须模拟额外的 Enter 输入 空行 ,尽管 PetSerAl 发现 [= =47=]单空行最后就够了
如果您希望看到此行为发生变化 and/or 需要对 -File -
的适当支持以将输入视为 脚本 ,请考虑将您的在 GitHub issue #3223.