【问题标题】:Captured output from a cmd.exe command is missing a final newline从 cmd.exe 命令捕获的输出缺少最后一个换行符
【发布时间】:2019-06-27 01:12:10
【问题描述】:

我正在尝试使用 Invoke-Expression 在 PowerShell 中调用内置的 cmd 命令(如 echo)并将其转换为字节数组,但命令输出中缺少换行符。

例子:

([Text.Encoding]::ASCII).GetBytes((iex "cmd /c echo."))

它不返回任何内容,而是返回换行符序列 (CRLF)。

【问题讨论】:

  • 请退后一步,描述您要解决的实际问题,而不是您认为的解决方案。为什么你试图通过Invoke-Expression 运行echo 而不是[Text.Encoding]::ASCII.GetBytes([Environment]::NewLine) 或简单的[byte[]](13,10) 来获取换行符字节序列?

标签: windows powershell cmd command-line command


【解决方案1】:

tl;博士:

PS> ([text.encoding]::ASCII).GetBytes(((cmd /c echo.) -join "`r`n") + "`r`n")
13
10

顺便说一句:iex (Invoke-Expression) should be avoided .

继续阅读以了解背景信息和注意事项。


PowerShell 从外部程序(例如 cmd.exe)捕获标准输出时,它会返回一个 array 的输出,尾随换行符序列修剪

顺便说一句:由[console]::OutputEncoding 报告的字符编码决定了 PowerShell 如何解释输出,在 Windows PowerShell 中默认为旧系统区域设置的 OEM代码页,并且,在撰写本文时,仍然在 PowerShell Core on Windows 中,尽管 will hopefully change soon,因为 PowerShell Core 否则使用(BOM-less)UTF-8 作为默认值编码。

在您的情况下,cmd /c echo. 发出了单个 Windows 换行序列 CRLF,在 PowerShell 术语中,它是 "`r`n"(您也可以使用 [Environment]::NewLine 来获取适合平台的换行字符串)。

PowerShell 将其解释为单个空行,并且由于不包括数组元素中的尾随换行符并且 PowerShell 解包单个元素数组,您最终会得到 '',即 空字符串 - 这就是([text.encoding]::ASCII).GetBytes() 调用没有输出的原因。

您可以通过以下方式将 PowerShell 创建的输出行数组重新组装为单个多行输出字符串:

  • 用换行符连接数组元素 (-join "`r`n")
  • 附加最后一个尾随换行符 (+ "`r`n")

如上图。

注意事项:这个“重组”做了两个假设,这可能并不总是正确的:

  • 外部程序确实发出了 Windows CRLF 序列,而不是 UNIX LF-only 字符。

    • 但实际上,这种差异在 PowerShell 中并不重要,因为它可互换接受两种换行符形式。
  • 外部程序确实发出了尾随换行符 - 这通常是正确的,但不一定是正确的。

如果这些假设有问题,将输出重定向到一个文件读取那个 - 如your own answer - 是正确的解决方案.

警告:Windows PowerShell 中的> 默认创建 UTF-16LE 文件(并且总是附加换行符),因此您不会得到 ASCII 字节;因此,使用cmd自己的 重定向来生成文件(它将使用chcp 指示的旧版OEM 编码,通常是ASCII 的超集) :

  # Note that the `>` is *inside the quoted string* to ensure that it is
  # cmd.exe that interprets it.
  # (...) around `echo.` ensures that the space before `>` doesn't become
  # part of the output.
  PS> cmd /c '(echo.) >out.txt'; [IO.File]::ReadAllBytes("$PWD\out.txt")
  13
  10

【讨论】:

    【解决方案2】:

    我找到了解决方案。不完美,但我会将输出写入文件,使用[System.IO.File]::ReadAllBytes("path_to_the_file") 读取它 并保存到变量

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-04
      • 1970-01-01
      • 2015-04-17
      • 1970-01-01
      • 2021-09-22
      • 2012-11-22
      • 1970-01-01
      • 2021-05-29
      相关资源
      最近更新 更多