简体   繁体   English

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

[英]Captured output from a cmd.exe command is missing a final newline

I'm trying to call a built-in cmd command like echo in PowerShell using Invoke-Expression and convert it to a byte array, but the newlines are missing from the command output. 我正在尝试使用Invoke-Expression在PowerShell中Invoke-Expression诸如echo的内置cmd命令并将其转换为字节数组,但是命令输出中缺少换行符。

Example: 例:

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

It returns nothing instead of a newline sequence (CRLF). 它不返回任何内容,而不是换行序列(CRLF)。

I found a solution. 我找到了解决方案。 Not perfect but i will write output to file, read it with [System.IO.File]::ReadAllBytes("path_to_the_file") and save to variable 并不完美,但是我将输出写入文件,使用[System.IO.File]::ReadAllBytes("path_to_the_file")读取并保存到变量

tl;dr: tl; dr:

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

As an aside: iex ( Invoke-Expression ) should be avoided . iex应该避免使用iexInvoke-Expression

Read on for background information and caveats. 请继续阅读以获取背景信息和注意事项。


When PowerShell captures stdout output from an external program such as cmd.exe , it returns an array of output lines , with the trailing newline sequence trimmed from each. PowerShell捕获来自外部程序(例如cmd.exe stdout输出时 ,它将返回输出 数组 ,并从每个输出行中修剪尾随的换行符序列。

As an aside: It is the character encoding reported by [console]::OutputEncoding that determines how PowerShell interprets the output, which in Windows PowerShell defaults to the legacy system locale's OEM code page, and, as of this writing, also - still -in PowerShell Core on Windows , though that will hopefully change soon , given that PowerShell Core otherwise uses (BOM-less) UTF-8 as the default encoding. [console]::OutputEncoding[console]::OutputEncoding[console]::OutputEncoding报告的字符编码确定PowerShell如何解释输出,在Windows PowerShell中默认为旧系统语言环境的OEM代码页,并且在撰写本文时,仍然-在Windows上的 PowerShell Core ,尽管希望 PowerShell 很快改变 ,因为PowerShell Core否则将使用(无BOM)UTF-8作为默认编码。

In your case, cmd /c echo. 在您的情况下, cmd /c echo. emitted a single Windows newline sequence, CRLF, which, in PowerShell terms, is "`r`n" (you can also use [Environment]::NewLine to obtain a platform-appropriate newline string). 发出了单个Windows换行符序列CRLF,以PowerShell术语来说,它是"`r`n" (您也可以使用[Environment]::NewLine获得适合于平台的换行符)。

PowerShell interprets that as a single empty line, and, due to not including the trailing newline in the array elements and PowerShell unwrapping a single-element array, you end up with '' , ie, the empty string - this is why the ([text.encoding]::ASCII).GetBytes() call produced no output. PowerShell会将其解释为一个空行,并且由于不将尾随换行符包含在数组元素中,并且PowerShell展开了一个单元素数组,因此您最终得到了'' ,即空字符串 -这就是([text.encoding]::ASCII).GetBytes()调用未产生任何输出。

You can reassemble the output-lines array that PowerShell created into a single, multi-line output string by: 您可以通过以下方法 PowerShell创建的输出行数组重组为一个多行输出字符串:

  • joining the array elements with newlines ( -join "`r`n" ) 用换行符连接数组元素( -join "`r`n"
  • appending a final trailing newline ( + "`r`n" ) 追加最后的尾随换行符( + "`r`n"

as shown above. 如上图所示。

Caveats : This "reassembly" makes two assumptions that may not always be true: 注意事项 :这种“重组”有两个可能并不总是正确的假设

  • That the external program really emitted Windows CRLF sequences and not UNIX LF-only characters. 外部程序确实发出了Windows CRLF序列,而不是仅UNIX LF字符。

    • In practice, however, that difference rarely matters in PowerShell, because it accepts both newline forms interchangeably . 但是,实际上,这种差异在PowerShell中几乎不重要,因为它可以互换地接受两种换行形式。
  • That the external program really emitted a trailing newline - which is typically, but not necessarily true. 外部程序确实发出了尾随换行符-通常,但不一定如此。

If these assumptions are problematic, redirecting the output to a file and reading that - as in your own answer - is the right solution. 如果这些假设有问题,那么将输出重定向到文件并按照您自己的答案 读取 文件是正确的解决方案。

Caveat : > in Windows PowerShell creates UTF-16LE files by default (and also invariably appends a newline), so you won't get ASCII bytes; 警告>在Windows PowerShell中默认创建UTF-16LE文件(也总是附加一个新行),这样你就不会得到ASCII字节; therefore, use cmd 's own redirection to produce the file (which will use the legacy OEM encoding indicated by chcp , which is typically a superset of 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM