从cmd.exe命令捕获的输出缺少最后一个换行符

时间:2019-02-02 19:34:31

标签: windows powershell cmd command-line command

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

示例:

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

它没有返回,而不是一个新行序列(CRLF)。

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

tl; dr:

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代码页,并且在撰写本文时,也仍然在Windows上的PowerShell Core 中,尽管该will hopefully change soon仍然存在,因为PowerShell Core否则会使用(无BOM的)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字符。

    • 但是,实际上,这种差异在PowerShell中几乎没有关系,因为它可以互换地接受两种换行形式。
  • 外部程序确实发出了 trailing 换行符-通常,但不一定如此。

如果这些假设有问题,则将输出重定向到文件读取 (如your own answer)是正确的解决方案。

注意事项:Windows PowerShell中的>默认情况下会创建UTF-16LE文件(并且总是会添加换行符),因此您不会得到 ASCII 字节因此,请使用cmd own 重定向来生成文件(该文件将使用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