对外部程序配管文本附加尾随换行符 [英] Piping Text To An External Program Appends A Trailing Newline

查看:137
本文介绍了对外部程序配管文本附加尾随换行符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



Linux终端(CygWin,Bash)对于Windows等)和Windows命令提示符都显示相同的散列,因为PowerShell显示的是不同的散列值。


$ b

解决方案

tl; dr:



键用于避免 PowerShell的管道 ,以便防止隐含的追加换行符




  • 如果您正在运行您在 Unix 类平台上的命令(使用PowerShell Core ):




  sh -cprintf%s'string'| openssl dgst -sha256 -hmac authcode

printf%s 可移植的替代 echo -n 如果字符串包含' chars。, double 它们或使用`...`引用。




  • 如果您需要在 Windows 上通过 cmd.exe cmd.exe 不会直接支持没有尾随换行符的回显:

  • ul>



      cmd / c< NUL set / p =`string`| openssl dgst -sha256 -hmac authcode

    请注意,必须存在 | 之前,为了解决此问题,请参阅本答案



    如果字符串包含非ASCII字符 你在Windows PowerShell中运行;在这种情况下,首先将 $ OutputEncoding 设置为目标实用程序期望的编码UTF-8: $ OutputEncoding = [Text.Utf8Encoding] :: new()







    • PowerShell,从Windows PowerShell v5.1 / PowerShell Core v6.0.0开始,总是附加尾随换行符当您通过管道将没有任何字符串的字符串发送到外部实用程序时,这是您观察到的差异的原因(即,换行符将会是b ea仅在Unix平台上使用LF,在Windows上使用CRLF序列)。



      另外,当涉及到将数据传输到外部程序时,PowerShell的管道总是基于 text 基于内部基于UTF-16LE的PowerShell(.NET)字符串将根据存储在自动 $ OutputEncoding 变量中的编码进行转码,该变量默认为 Windows
      PowerShell,以及PowerShell Core 中的UTF-8编码(在Windows和Unix类平台上)。


      • 在PowerShell Core 中,更改为正在讨论,以管理外部程序之间的原始字节流。 那么PowerShell中的 echo -n 会产生一个没有尾随换行符的字符串,因此偶然为了完整起见,这里有一个解释:


        • echo 是别名PowerShell的 写入输出 cmdlet,在管道到外部程序的环境中,将文本写入程序的标准输入 next 管道段(类似于Bash / cmd.exe的 echo )。

        • -n 被解释为写入输出 - 不允许 switch。
        • -NoEnumerate 仅适用于编写多个对象,因此在此处不起作用。因此,简而言之:在PowerShell中, echo -nstring Write-输出-NoEnumeratestring,因为只输出一个字符串 - 与 Write-Out相同放置string,这反过来与使用string相同,依靠PowerShell的隐式输出行为。

        • 写入输出没有选择来抑制尾随的换行符,即使这样做,使用管道传送到 external 程序会将其添加回来。



      I have been comparing hash values between multiple systems and was surprised to find that PowerShells hash values are different than that of other terminals.

      Linux terminals (CygWin, Bash for Windows, etc.) and Windows Command Prompt are all showing the same hash where as PowerShell is showing a different hash value.

      This was tested using SHA256 but found the same issue when using other algorithms like md5.

      Encoding Update:

      Tried changing the PShell encoding but it did not have any effect on the returned hash values.

      [Console]::OutputEncoding.BodyName 
      iso-8859-1
      [Console]::OutputEncoding = [Text.UTF8Encoding]::UTF8
      utf-8
      

      GitHub PowerShell Issue

      https://github.com/PowerShell/PowerShell/issues/5974

      解决方案

      tl;dr:

      The key is to avoid PowerShell's pipeline in favor of the native shell's, so as to prevent implicit addition of a trailing newline:

      • If you're running your command on a Unix-like platform (using PowerShell Core):

      sh -c "printf %s 'string' | openssl dgst -sha256 -hmac authcode"
      

      printf %s is the portable alternative to echo -n. If the string contains ' chars., double them or use `"...`" quoting instead.

      • In case you need to do this on Windows via cmd.exe, things get even trickier, because cmd.exe doesn't directly support echoing without a trailing newline:

      cmd /c "<NUL set /p =`"string`"| openssl dgst -sha256 -hmac authcode"
      

      Note that there must be no space before | for this to work. For an explanation and the limitations of this solution, see this answer of mine.

      Encoding issues would only arise if the string contained non-ASCII characters and you're running in Windows PowerShell; in that event, first set $OutputEncoding to the encoding that the target utility expects, typically UTF-8: $OutputEncoding = [Text.Utf8Encoding]::new()


      • PowerShell, as of Windows PowerShell v5.1 / PowerShell Core v6.0.0, invariably appends a trailing newline when you send a string without one via the pipeline to an external utility, which is the reason for the difference you're observing (that trailing newline will be a LF only on Unix platforms, and a CRLF sequence on Windows).

        • You can keep track of efforts to address this problem in this GitHub issue opened by the OP.
      • Additionally, PowerShell's pipeline is invariably text-based when it comes to piping data to external programs; the internally UTF-16LE-based PowerShell (.NET) strings are transcoded based on the encoding stored in the automatic $OutputEncoding variable, which defaults to ASCII-only encoding in Windows PowerShell, and to UTF-8 encoding in PowerShell Core (both on Windows and on Unix-like platforms).

      • The fact that echo -n in PowerShell does not produce a string without a trailing newline is therefore incidental to your problem; for the sake of completeness, here's an explanation:

        • echo is an alias for PowerShell's Write-Output cmdlet, which - in the context of piping to external programs - writes text to the standard input of the program in the next pipeline segment (similar to Bash / cmd.exe's echo).
        • -n is interpreted as an (unambiguous) abbreviation for Write-Output's -NoEnumerate switch.
        • -NoEnumerate only applies when writing multiple objects, so it has no effect here.
        • Therefore, in short: in PowerShell, echo -n "string" is the same as Write-Output -NoEnumerate "string", which - because only a single string is output - is the same as Write-Output "string", which, in turn, is the same as just using "string", relying on PowerShell's implicit output behavior.
        • Write-Output has no option to suppress a trailing newline, and even if it did, using a pipeline to pipe to an external program would add it back in.

      这篇关于对外部程序配管文本附加尾随换行符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆