将文本管道到外部程序会附加一个尾随换行符

Pie*_*Pie 7 linux powershell hash newline pipe

我一直在比较多个系统之间的哈希值,并惊讶地发现PowerShells哈希值与其他终端的哈希值不同.

Linux终端(CygWin,Bash for Windows等)和Windows命令提示符都显示相同的哈希,而PowerShell显示不同的哈希值.

Linux_Vs_PShell_Hash_Compare.png

这是使用SHA256测试的,但在使用其他算法(如md5)时发现了同样的问题.

编码更新:

尝试更改PShell编码,但它对返回的哈希值没有任何影响.

[Console]::OutputEncoding.BodyName 
iso-8859-1
[Console]::OutputEncoding = [Text.UTF8Encoding]::UTF8
utf-8
Run Code Online (Sandbox Code Playgroud)

GitHub PowerShell问题

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

mkl*_*nt0 6

tl;博士:

当 PowerShell 将字符串通过管道传输到外部程序时

因此,关键是避免使用PowerShell 的管道,而使用本机 shell管道,以防止隐式添加尾随换行符

  • 如果您在类 Unix平台上运行命令(使用 PowerShell Core):
sh -c "printf %s 'string' | openssl dgst -sha256 -hmac authcode"
Run Code Online (Sandbox Code Playgroud)

printf %s是 的便携式替代品echo -n。如果字符串包含'字符,请将它们加倍或使用`"...`"引号代替。

  • 如果您需要在Windows 上通过cmd.exe执行此操作,事情会变得更加棘手,因为cmd.exe不直接支持没有尾随换行符的回显:
cmd /c "<NUL set /p =`"string`"| openssl dgst -sha256 -hmac authcode"
Run Code Online (Sandbox Code Playgroud)

请注意,此操作之前 必须没有空间|。有关此解决方案的解释和限制,请参阅此答案

仅当字符串包含非 ASCII 字符并且您在Windows PowerShell 中运行时才会出现编码问题;在这种情况下,首先设置$OutputEncoding为目标实用程序期望的编码,通常是 UTF-8:$OutputEncoding = [Text.Utf8Encoding]::new()


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

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

    • 在 PowerShell Core 中正在讨论外部程序之间传输原始字节流的变化
  • 因此,echo -n在 PowerShell 中不会产生没有尾随换行符的字符串这一事实是您的问题的附带条件;为了完整起见,这里有一个解释:

    • echo是 PowerShell 的Write-Outputcmdlet的别名,它 - 在管道到外部程序的上下文中- 将文本写入下一个管道段中程序的标准输入(类似于 Bash / cmd.exe 的echo)。
    • -n被解释为Write-Output's-NoEnumerate开关的(明确的)缩写。
    • -NoEnumerate仅在写入多个对象时适用,因此在此处不起作用。
    • 因此,简而言之:在 PowerShell 中,echo -n "string"与 相同Write-Output -NoEnumerate "string"- 因为仅输出单个字符串 - 与 相同Write-Output "string",这又与仅使用相同"string",依赖于PowerShell 的隐式输出行为。
    • Write-Output没有选项来抑制尾随的换行符,即使这样做了,使用管道通过管道连接到外部程序也会将其添加回。


归档时间:

查看次数:

245 次

最近记录:

7 年,11 月 前