在变量中存储 cmdlet 响应时出现 PowerShell 编码问题
PowerShell encoding issue when storing cmdlet response in variable
我花了大约一个小时试图弄清楚这里发生了什么,但我根本无法找出原因,也没有偶然发现解决方法。
当我 运行 winget upgrade
数据 return 正确编码时:
然而,如果我将 winget 升级的响应存储在一个变量中 ($winget = winget upgrade; $winget;
),一些字符会中断,这似乎是一个编码问题:
像这样的 cmdlet 总是 return 字符串到 PowerShell,所以我猜想将响应分配给变量是应用了一些默认的文本编码,也许来自我的 PowerShell 配置文件?我已经尝试将大部分常用代码转换为变量,但最终完全破坏了数据。
我什至把所有可能的编码类型的数据都转储了出来,但它们都坏了:
winget upgrade | Out-File -FilePath C:\tmp\test1.txt -Encoding ascii
winget upgrade | Out-File -FilePath C:\tmp\test3.txt -Encoding default
winget upgrade | Out-File -FilePath C:\tmp\test4.txt -Encoding string
winget upgrade | Out-File -FilePath C:\tmp\test5.txt -Encoding unicode
winget upgrade | Out-File -FilePath C:\tmp\test7.txt -Encoding utf32
winget upgrade | Out-File -FilePath C:\tmp\test8.txt -Encoding utf7
winget upgrade | Out-File -FilePath C:\tmp\test9.txt -Encoding utf8
我已经通过重新编码字符串设法影响错误字符,bt 没有解决问题:
$originalBytes = [Text.Encoding]::Default.GetBytes('Microsoft Visual C++ 2013 Redistributable (x6')
[Text.Encoding]::Utf8.GetString($originalBytes)
我知道你说替换字符不是一个选项。我很想知道你想出了什么。对于我们其他人,这里有一些代码可以将 winget upgrade
的输出转换为可用对象。
(winget upgrade) -replace 'ΓǪ|…|…',' ' | ForEach-Object {
if($_ -match '(.+?)\s{2,}(.+?)\s+(\S+)\s+(\S+)\s+(\S+)$'){
$Matches[1..5] -join '|'
}
} | ConvertFrom-Csv -Delimiter '|'
这里是列表形式的默认输出
Name : Cisco Webex Meetings
Id : Cisco.CiscoWebexMeetings
Version : 41.9.5
Available : 41.12.2.15
Source : winget
Name : Discord
Id : Discord.Discord
Version : 0.0.309
Available : 1.0.9003
Source : winget
Name : GitHub Desktop
Id : GitHub.GitHubDesktop
Version : 2.9.0
Available : 2.9.4
Source : winget
而当使用 Format-Table
Name Id Version Available Source
---- -- ------- --------- ------
Visual Studio Community 2019 Microsoft.VisualStudio.2019.Community 16.10.31410.357 16.11.7 winget
Cisco Webex Meetings Cisco.CiscoWebexMeetings 41.9.5 41.12.2.15 winget
Discord Discord.Discord 0.0.309 1.0.9003 winget
我已经在 5.1、7.2、ISE 和 Visual Studio 代码中进行了测试。
感谢@JosefZ 分享解决方案,可在此处找到:
这是[console]::OutputEncoding
的输出:
PS C:\> [console]::OutputEncoding
IsSingleByte : True
BodyName : ibm850
EncodingName : Western European (DOS)
HeaderName : ibm850
WebName : ibm850
WindowsCodePage : 1252
IsBrowserDisplay : False
IsBrowserSave : False
IsMailNewsDisplay : False
IsMailNewsSave : False
EncoderFallback : System.Text.InternalEncoderBestFitFallback
DecoderFallback : System.Text.InternalDecoderBestFitFallback
IsReadOnly : True
CodePage : 850
这是[Console]::Out
的输出:
PS C:\> [Console]::Out
Encoding FormatProvider NewLine
-------- -------------- -------
System.Text.SBCSCodePageEncoding en-GB ...
使用 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8
将我的控制台输出更改为 UTF-8 已解决问题。
现在,当我将 cmdlet 响应存储在一个变量中时,世界上一切都是正确的:
PS C:\> [Console]::OutputEncoding = [System.Text.Encoding]::UTF8
PS C:\> $winget = winget upgrade
PS C:\> $winget
Name Id Version Available Source
-----------------------------------------------------------------------------------------------------------------------
Signal OpenWhisperSystems.Signal 5.20.0 5.23.1 winget
Cisco Webex Meetings Cisco.CiscoWebexMeetings 41.9.5 41.12.2.15 winget
Audacity Audacity.Audacity 3.0.4 3.1.2 winget
Docker Desktop Docker.DockerDesktop 4.1.1 4.2.0 winget
Git Git.Git 2.33.0.2 2.34.0 winget
MongoDB Compass MongoDB.Compass.Full 1.28.4 1.29.4.0 winget
TeamViewer TeamViewer.TeamViewer 15.22.3 15.23.9 winget
Visual Studio Community 2019 Microsoft.VisualStudio.2019.Community 16.11.3 16.11.7 winget
Insomnia Insomnia.Insomnia 2021.5.3 2021.6.0 winget
Microsoft Visual C++ 2013 Redistributable (x6… Microsoft.VC++2013Redist-x64 12.0.30501.0 12.0.40664.0 winget
Microsoft Visual C++ 2015-2019 Redistributabl… Microsoft.VC++2015-2019Redist-x64 14.29.30133.0 14.29.30135.0 winget
Microsoft Visual C++ 2015-2019 Redistributabl… Microsoft.VC++2015-2019Redist-x86 14.29.30133.0 14.29.30135.0 winget
Node.js LTS OpenJS.NodeJS.LTS 14.17.6 16.13.0 winget
Microsoft Visual C++ 2015-2019 Redistributabl… Microsoft.VC++2015-2019Redist-x64 14.28.29914.0 14.29.30135.0 winget
ScreenToGif NickeManarin.ScreenToGif 2.33.1 2.34.1 winget
MongoDB MongoDB.Server 5.0.2 5.1.0 winget
AWS Command Line Interface Amazon.AWSCLI 2.2.46.0 2.3.7.0 winget
Chrome Remote Desktop Host Google.ChromeRemoteDesktop 92.0.4515.41 96.0.4664.39 winget
Microsoft Visual C++ 2013 Redistributable (x8… Microsoft.VC++2013Redist-x86 12.0.30501.0 12.0.40664.0 winget
19 upgrades available.
我花了大约一个小时试图弄清楚这里发生了什么,但我根本无法找出原因,也没有偶然发现解决方法。
当我 运行 winget upgrade
数据 return 正确编码时:
然而,如果我将 winget 升级的响应存储在一个变量中 ($winget = winget upgrade; $winget;
),一些字符会中断,这似乎是一个编码问题:
cmdlet 总是 return 字符串到 PowerShell,所以我猜想将响应分配给变量是应用了一些默认的文本编码,也许来自我的 PowerShell 配置文件?我已经尝试将大部分常用代码转换为变量,但最终完全破坏了数据。
我什至把所有可能的编码类型的数据都转储了出来,但它们都坏了:
winget upgrade | Out-File -FilePath C:\tmp\test1.txt -Encoding ascii
winget upgrade | Out-File -FilePath C:\tmp\test3.txt -Encoding default
winget upgrade | Out-File -FilePath C:\tmp\test4.txt -Encoding string
winget upgrade | Out-File -FilePath C:\tmp\test5.txt -Encoding unicode
winget upgrade | Out-File -FilePath C:\tmp\test7.txt -Encoding utf32
winget upgrade | Out-File -FilePath C:\tmp\test8.txt -Encoding utf7
winget upgrade | Out-File -FilePath C:\tmp\test9.txt -Encoding utf8
我已经通过重新编码字符串设法影响错误字符,bt 没有解决问题:
$originalBytes = [Text.Encoding]::Default.GetBytes('Microsoft Visual C++ 2013 Redistributable (x6')
[Text.Encoding]::Utf8.GetString($originalBytes)
我知道你说替换字符不是一个选项。我很想知道你想出了什么。对于我们其他人,这里有一些代码可以将 winget upgrade
的输出转换为可用对象。
(winget upgrade) -replace 'ΓǪ|…|…',' ' | ForEach-Object {
if($_ -match '(.+?)\s{2,}(.+?)\s+(\S+)\s+(\S+)\s+(\S+)$'){
$Matches[1..5] -join '|'
}
} | ConvertFrom-Csv -Delimiter '|'
这里是列表形式的默认输出
Name : Cisco Webex Meetings
Id : Cisco.CiscoWebexMeetings
Version : 41.9.5
Available : 41.12.2.15
Source : winget
Name : Discord
Id : Discord.Discord
Version : 0.0.309
Available : 1.0.9003
Source : winget
Name : GitHub Desktop
Id : GitHub.GitHubDesktop
Version : 2.9.0
Available : 2.9.4
Source : winget
而当使用 Format-Table
Name Id Version Available Source
---- -- ------- --------- ------
Visual Studio Community 2019 Microsoft.VisualStudio.2019.Community 16.10.31410.357 16.11.7 winget
Cisco Webex Meetings Cisco.CiscoWebexMeetings 41.9.5 41.12.2.15 winget
Discord Discord.Discord 0.0.309 1.0.9003 winget
我已经在 5.1、7.2、ISE 和 Visual Studio 代码中进行了测试。
感谢@JosefZ 分享解决方案,可在此处找到:
这是[console]::OutputEncoding
的输出:
PS C:\> [console]::OutputEncoding
IsSingleByte : True
BodyName : ibm850
EncodingName : Western European (DOS)
HeaderName : ibm850
WebName : ibm850
WindowsCodePage : 1252
IsBrowserDisplay : False
IsBrowserSave : False
IsMailNewsDisplay : False
IsMailNewsSave : False
EncoderFallback : System.Text.InternalEncoderBestFitFallback
DecoderFallback : System.Text.InternalDecoderBestFitFallback
IsReadOnly : True
CodePage : 850
这是[Console]::Out
的输出:
PS C:\> [Console]::Out
Encoding FormatProvider NewLine
-------- -------------- -------
System.Text.SBCSCodePageEncoding en-GB ...
使用 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8
将我的控制台输出更改为 UTF-8 已解决问题。
现在,当我将 cmdlet 响应存储在一个变量中时,世界上一切都是正确的:
PS C:\> [Console]::OutputEncoding = [System.Text.Encoding]::UTF8
PS C:\> $winget = winget upgrade
PS C:\> $winget
Name Id Version Available Source
-----------------------------------------------------------------------------------------------------------------------
Signal OpenWhisperSystems.Signal 5.20.0 5.23.1 winget
Cisco Webex Meetings Cisco.CiscoWebexMeetings 41.9.5 41.12.2.15 winget
Audacity Audacity.Audacity 3.0.4 3.1.2 winget
Docker Desktop Docker.DockerDesktop 4.1.1 4.2.0 winget
Git Git.Git 2.33.0.2 2.34.0 winget
MongoDB Compass MongoDB.Compass.Full 1.28.4 1.29.4.0 winget
TeamViewer TeamViewer.TeamViewer 15.22.3 15.23.9 winget
Visual Studio Community 2019 Microsoft.VisualStudio.2019.Community 16.11.3 16.11.7 winget
Insomnia Insomnia.Insomnia 2021.5.3 2021.6.0 winget
Microsoft Visual C++ 2013 Redistributable (x6… Microsoft.VC++2013Redist-x64 12.0.30501.0 12.0.40664.0 winget
Microsoft Visual C++ 2015-2019 Redistributabl… Microsoft.VC++2015-2019Redist-x64 14.29.30133.0 14.29.30135.0 winget
Microsoft Visual C++ 2015-2019 Redistributabl… Microsoft.VC++2015-2019Redist-x86 14.29.30133.0 14.29.30135.0 winget
Node.js LTS OpenJS.NodeJS.LTS 14.17.6 16.13.0 winget
Microsoft Visual C++ 2015-2019 Redistributabl… Microsoft.VC++2015-2019Redist-x64 14.28.29914.0 14.29.30135.0 winget
ScreenToGif NickeManarin.ScreenToGif 2.33.1 2.34.1 winget
MongoDB MongoDB.Server 5.0.2 5.1.0 winget
AWS Command Line Interface Amazon.AWSCLI 2.2.46.0 2.3.7.0 winget
Chrome Remote Desktop Host Google.ChromeRemoteDesktop 92.0.4515.41 96.0.4664.39 winget
Microsoft Visual C++ 2013 Redistributable (x8… Microsoft.VC++2013Redist-x86 12.0.30501.0 12.0.40664.0 winget
19 upgrades available.