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

标签 linux powershell hash pipe newline

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

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

GitHub PowerShell 问题

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

最佳答案

tl;博士:
当 PowerShell 将字符串通过管道传输到外部程序时 :

  • 它使用存储在 $OutputEncoding preference variable 中的字符编码对其进行编码。
  • 它总是附加一个尾随(适合平台的)换行符。

  • 因此,关键是避免 PowerShell 的管道 赞成 native shell 的,以便 防止隐式添加尾随换行符 :
  • 如果您在 上运行您的命令Unix 类似平台(使用 PowerShell Core):
  • sh -c "printf %s 'string' | openssl dgst -sha256 -hmac authcode"
    
    printf %secho -n 的便携替代品.如果字符串包含 '字符。,将它们加倍或使用 `"...`"而是引用。
  • 如果您需要在 上执行此操作Windows 通过 cmd.exe ,事情变得更加棘手,因为 cmd.exe不直接支持没有尾随换行符的回显:
  • cmd /c "<NUL set /p =`"string`"| openssl dgst -sha256 -hmac authcode"
    
    注意|前不能有空格为了这个工作。有关此解决方案的说明和局限性,请参阅 this answer .
    仅当字符串包含非 ASCII 字符并且您在 Windows PowerShell 中运行时才会出现编码问题;在那个事件中,第一组$OutputEncoding到目标实用程序期望的编码,通常是 UTF-8:$OutputEncoding = [Text.Utf8Encoding]::new()
  • 从 Windows PowerShell v5.1/PowerShell (Core) v7.2 开始,当您通过管道将没有字符串的字符串发送到外部实用程序时,PowerShell 总是会附加一个尾随换行符 ,这就是您观察到的差异的原因(尾随换行符仅在 Unix 平台上为 LF,而在 Windows 上为 CRLF 序列)。
  • 您可以在 GitHub issue #5974 中跟踪解决此问题的努力,由 OP 打开。

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

  • 事实echo -n在 PowerShell 中不会产生没有尾随换行符的字符串,因此您的问题是附带的;为了完整起见,这里有一个解释:
  • echo是 PowerShell Write-Output 的别名cmdlet,它 - 在管道到外部程序的上下文中 - 将文本写入下一个管道段中程序的标准输入(类似于 Bash/cmd.exe 的 echo )。
  • -n被解释为 Write-Output 的(明确的)缩写的 -NoEnumerate转变。
  • -NoEnumerate仅在写入多个对象时适用,因此在此处不起作用。
  • 因此,简而言之:在 PowerShell 中,echo -n "string"Write-Output -NoEnumerate "string" 相同,这 - 因为只输出一个字符串 - 与 Write-Output "string" 相同,反过来,这与仅使用 "string" 相同,依赖于 PowerShell 的隐式输出行为。
  • Write-Output没有选项可以取消尾随换行符,即使这样做,使用管道将其通过管道传输到外部程序也会将其添加回。

  • 关于linux - 管道文本到外部程序附加一个尾随换行符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48371447/

    相关文章:

    c# - 对象.GetHashCode

    java - 用于 fips 的 Bouncy CaSTLe 无法在 Linux 虚拟机上运行

    azure - 如何使用 PowerShell 创建使用帐户 key 签名的 Azure 容器 SAS token ?

    c - 高速缓存的哈希函数好吗?

    python - 定义 `__eq__` 的类型是不可散列的?

    powershell - 使用 PowerShell 复制目录结构

    android - 构建失败,在 React Native android 中出现异常

    linux - 将值重新分配给 spec 文件中的 %define 变量 - RPM

    特定 ISR 后上下文切换到特定进程

    excel - Ping 脚本不导出结果