首页 > 解决方案 > 为什么 Powershell 输出在 5.1 和 Core 7.1.4 之间不同

问题描述

我有一个 PowerShell 代码块,它运行一个命令,然后对其进行按摩并将其写入一个文本文件。

$commandOutput = &"C:\Program Files (x86)\Dell EMC\Unity\Unisphere CLI\uemcli" -d $frame -noHeader /stor/config/pool/sr show
foreach ($idline in $commandOutput)
{
    if ($idline -match ' ID ')
    {
    $subline = $idline.substring(6,($idline.length - 6))
    $writeline = $subline.trim()
    #$writeline
    }
    elseif ($idline -match 'Total pool space used')
    {
    $Sleft,$Sright = $idline.Split('(',2)
    $writeline = $Sleft.trim()
    #    $writeline
    #    write-host ""
    } 
 
    else {$writeline = $idline.trim()}
    #$writeline
    Add-Content -path $outdir\$frame-intrim.txt -value $writeline -Encoding UTF8
    }

当我在 PowerShell 5.1 中运行它时,我得到:

ID                    = res_2
Name                  = asi-vcva-fs01
Resource type         = VMware NFS
Pool                  = pool_1
Total pool space used = 18025199894528
Health state          = OK (5)

当我在 PowerShell Core 7.1.4 中运行它时,我得到:

1 :          I D                                         =   r e s _ 2 
             N a m e                                     =   a s i - v c v a - f s 0 1 
             R e s o u r c e   t y p e                   =   V M w a r e   N F S 
             P o o l                                     =   p o o l _ 1 
             T o t a l   p o o l   s p a c e   u s e d   =   1 8 0 2 5 2 1 3 2 7 2 0 6 4   ( 1 6 . 3 T ) 
             H e a l t h   s t a t e                     =   O K   ( 5 )

这弄乱了脚本的其余部分。我尝试了 -Encoding UTF8 但没有任何改变。如何使它能够在 5.1 和 Core 7.1 中运行?

更多信息:

它以这种方式编写输出的原因是因为这是从输入中解析数据的方式。如何摆脱空格,特别是使其在两个版本的代码中都可用?

标签: powershellpowershell-7.0powershell-5.1

解决方案


我不知道为什么在这种情况下 PowerShell 版本之间的行为会有所不同,但它看起来像是uemcli输出 UTF-16LE ("Unicode") 编码的字符串

为了让 PowerShell 正确识别它们[1],(临时) 在调用之前设置
[Console]::OutputEncoding = [Text.Encoding]::Unicode


至于诊断特定外部程序使用的字符编码以及 PowerShell 如何对其进行解码:

  • 请参阅此答案的底部部分,它提供了两个辅助函数:

    • Debug-NativeInOutput帮助您诊断外部程序的输入和输出。

    • Invoke-WithEncoding使具有给定编码的外部程序调用更容易;例如,在您的情况下,您会调用:

      Invoke-WithEncoding -Encoding Unicode { 
        & "C:\Program Files (x86)\Dell EMC\Unity\Unisphere CLI\uemcli" -d $frame -noHeader /stor/config/pool/sr show
      }
      
  • 此答案包含另一个辅助函数 ,Debug-String它可以帮助您在一般字符串中查找非打印和非 ASCII 字符;例如,从 UTF-16LE 输出中错误解码的 ASCII 范围字符将导致该字符加上一个NUL( 0x0) 字符,该字符Debug-String将显示为`0.

    • 默认情况下,NUL字符在控制台中打印为空格,这就是您所看到的。

[1] 在后续处理中;请注意,直接显示的输出可能打印得很好,但是一旦 PowerShell解码输出,字符编码问题就可能出现,这总是在捕获变量中的输出或通过管道或文件发送输出的过程中发生。


推荐阅读