关于PowerShell Write-Host的行为问题:示例和文档未覆盖的部分
我正在使用Windows 11,我从一个桌面快捷方式运行我的PowerShell脚本,该快捷方式绑定到一个命令批处理文件,该批处理文件以以下命令启动PowerShell控制台:
start pwsh.exe -NoExit -NoProfile -ExecutionPolicy Bypass -Command ".\mtpc.ps1"
mtpc.ps1 包含以下PowerShell脚本代码:
[String] $NewLine = [Environment]::NewLine
Write-Host ""
# Case 1 - String String concatenation with line continuation:
Write-Host `
"0, $( $this.NewLine )" `
"1, $( $this.NewLine )" `
"2. $( $this.NewLine ) $( $this.NewLine )"
Write-Host ""
# Case 2 - String + String concatenation with line continuation:
Write-Host `
"3, $( $this.NewLine )" + `
"4, $( $this.NewLine )" + `
"5. $( $this.NewLine ) $( $this.NewLine )"
Write-Host ""
# Case 3 - String + String concatenation without line continuation:
Write-Host `
"6, $( $this.NewLine )" +
"7, $( $this.NewLine )" +
"8. $( $this.NewLine ) $( $this.NewLine )"
Write-Host ""
# Right output, but not the code I'm hoping to use:
Write-Host "0,"
Write-Host "1,"
Write-Host "2."
Write-Host ""
Write-Host ""
Write-Host ""
Write-Host "3,"
Write-Host "4,"
Write-Host "5."
Write-Host ""
Write-Host ""
Write-Host ""
Write-Host "6,"
Write-Host "7,"
Write-Host "8."
Write-Host ""
Write-Host ""
Write-Host ""
为什么前三个Write-Host语句的情况会输出这些结果:
前面的三条Write-Host语句的情况(除了Write-Host "" 的那些)没有输出 $this.NewLines字符串strings1,而是在存在+ 运算符的那些行中输出了未被双引号(")括起来的+ 运算符。
期望的结果:
在Copilot给出的示例或我所看到的PowerShell Write-Host文档中,没有关于换行字符串不会输出,或字符串连接表达式运算符会被添加到输出中的说明。
是的,显然可以通过使用更简单的Write-Host语句来避免这个问题,以得到我在本问题中展示的那种预期输出结果,但我不应该把它“简化”到那么低的程度。此外,原因也不是出在我的电脑或我的PowerShell配置上。我在一个在线lint网站上运行这段代码时,得到的结果也是完全相同的。
为什么会发生这些事情?
1 实际上,Write-Host的第三种情况在第6 部分后确实输出了换行,但它在同一输出行上也显示了+ 字符。相同语句的第7、8部分的输出与脚本前半部分的Write-Host语句类似。这不一致,增加了绕开方式的难度。请注意,该部分中所有Write-Host语句都遵循相同的代码模式,但并非全部以相同方式工作,因此不能依赖它们来产生所需结果。
解决方案
你不会得到换行,因为你正在尝试访问变量 $this 的属性 NewLine,但 $this 未定义。
自动变量 $this 只在类定义内部存在。
所以只需使用 $NewLine 而不是 $this.NewLine。
关于 Cases 1和 2 中的 +:你并没有连接字符串(这与换行续行无关,我也就不再讨论)。
你当前的上下文是你正在向一个cmdlet传递参数,所以需要通过将操作放在圆括号中来对它们进行分组。这是一个分组的说明。
这将生成你所期望的输出:
$NewLine = [Environment]::NewLine
Write-Host -Object ("3, $( $NewLine )" + "4, $( $NewLine )" + "5. $( $NewLine ) $( $NewLine )")
否则,你将把一个对象集合传递给 Write-Host,而 + 将只是“另一个未命名的字符串参数”,而不是一个运算符,相当于:
Write-Host -Object "3, $( $NewLine )" '+' "4, $( $NewLine )" '+' "5. $( $NewLine ) $( $NewLine )"
将集合传递给输出时发生的情况在 关于 Write-Host 的注释 中有说明:
当将集合写入主机时,集合中的元素将在同一行上以一个空格分隔输出。可通过Separator参数进行覆盖。
因此,作为替代,你可以添加 Separator 参数:
$NewLine = [Environment]::NewLine
Write-Host "3, " "4, " "5. " "" -Separator $NewLine
你的 Case 3 有点不同:
Write-Host `
"6, $( $this.NewLine )" +
"7, $( $this.NewLine )" +
"8. $( $this.NewLine ) $( $this.NewLine )"
这里发生的不是单一的 Write-Host,而是两次操作:
- 一个
Write-Host的cmdlet调用 - 一次字符串连接
Write-Host "6, $( $this.NewLine )" +
"7, $( $this.NewLine )" + "8. $( $this.NewLine ) $( $this.NewLine )"
由于第二行末尾没有换行续行,而且末尾的 + 是“只是另一个字符串参数”,你会得到与上面所述相同的情形。
随后又有另一行独立的代码,由于你不再处于传递参数的上下文中,这将按预期进行字符串连接。
你并没有把运算的结果赋值给变量,或通过管道传递给另一个cmdlet,因此PowerShell将把它直接输出到控制台(但在标准输出流中,而不是作为 Write-Host 控制台输出的一部分)。
如果你给 Write-Host 上色,你会看到只有 6, + 会以红色显示:
Write-Host -ForegroundColor Red `
"6, $( $NewLine )" +
"7, $( $NewLine )" +
"8. $( $NewLine ) $( $NewLine )"

