Powershell Unicode 字符 - Em Dash
Powershell Unicode Characters - Em Dash
我有一个 powershell 脚本,它使用以下命令从 API 中提取数据
Invoke-RestMethod -Method Post -Uri $WebServiceURL -Body $json -ContentType "Application/json"
API 服务器端的数据包含一个 Em Dash“–”。
当我使用 Postman 提取数据时,它会按原样显示 Em Dash,但是当我使用 Powershell 提取数据并打印输出时,它会显示一些奇怪的字符,如下所示。
OUPath=ABCD.COM/Test/All Users/India/Test/TestâOU/Desktop Users
Em Dash 打印为“â”。
我尝试使用以下命令转换 Powershell 的输出编码,但没有成功。
[Console]::OutputEncoding = [Text.Encoding]::Utf8
当前 Powershell 版本详细信息。
PS Codes> $PSVersionTable
Name Value
---- -----
PSVersion 5.1.19041.1
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.19041.1
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
默认输出编码如下:
PS Codes> [Console]::OutputEncoding
IsSingleByte : True
BodyName : IBM437
EncodingName : OEM United States
HeaderName : IBM437
WebName : IBM437
WindowsCodePage : 1252
IsBrowserDisplay : False
IsBrowserSave : False
IsMailNewsDisplay : False
IsMailNewsSave : False
EncoderFallback : System.Text.InternalEncoderBestFitFallback
DecoderFallback : System.Text.InternalDecoderBestFitFallback
IsReadOnly : True
CodePage : 437
我过去在这里回答过几个类似的问题(参见 https://whosebug.com/a/58542493/3156906 and https://whosebug.com/a/66404671/3156906),所以我 认为 这个问题是几个因素的组合: :
- 服务器正在发送一个编码为 utf-8 的响应,但是 没有 在
Content-Encoding
header
- 在没有字符集的情况下,PowerShell 遵循 HTTP 规范并解码为 ISO-8859-1,最终会得到一个您正在逐字写入控制台的损坏的字符串
- Postman 可能检测到不知何故响应是 utf-8,即使没有字符集,并且正在解码响应流
当然,如果是一个字符集参数,那么这个答案的其余部分都是废话!
无论如何,这里有一段简单的脚本可以重现该问题:
# server encodes response text using utf8
PS> $text = "`u{2014}"; # em dash
PS> $bytes = [System.Text.Encoding]::UTF8.GetBytes($text);
PS> write-host $bytes;
226 128 148
# client (Invoke-RestMethod) decodes bytes as ISO-8859-1
PS> $text = [System.Text.Encoding]::GetEncoding("ISO-8859-1").GetString($bytes);
PS> write-host $text;
â
不幸的是,在您的情况下,处理是不可逆的,因为正如 @JosefZ 在评论中指出的那样,一些编码字节在以下情况下被“扼杀”(即丢弃)字节流被解码。
我能真正建议的是:
- 修复 API(如果您有访问权限),使其发送一个“charset=utf-8”参数,或者,
- 也许 hard-code 一些特殊处理可以在进行下游处理之前修复已知的错误名称
- 或者,使用
Invoke-RestMethod
的 -OutFile
参数将响应字节写入文件而不对其进行解码,然后将其作为 utf-8 编码文件读回。
顺便说一句,这是我以前用来检测 encoding/decoding 对导致给定的修改的脚本 - 我每次都是从头开始写的,所以我也可以 post这次在这里,所以我可以稍后再找到它:-)。
$original = "`u{2014}"; # em dash
$mangled = "`u{00E2}"; # circumflex a
$encodings = [System.Text.Encoding]::GetEncodings() | sort-object -Property "Name";
foreach( $source in $encodings )
{
foreach( $target in $encodings )
{
$bytes = [System.Text.Encoding]::GetEncoding($source.Name).GetBytes($original);
$text = [System.Text.Encoding]::GetEncoding($target.Name).GetString($bytes);
if( $text -eq $mangled )
{
write-host "original string = '$original'";
write-host "mangled string = '$mangled'";
write-host " source encoding = '$($source.Name)'";
write-host " target encoding = '$($target.Name)'";
}
}
}
我有一个 powershell 脚本,它使用以下命令从 API 中提取数据
Invoke-RestMethod -Method Post -Uri $WebServiceURL -Body $json -ContentType "Application/json"
API 服务器端的数据包含一个 Em Dash“–”。
当我使用 Postman 提取数据时,它会按原样显示 Em Dash,但是当我使用 Powershell 提取数据并打印输出时,它会显示一些奇怪的字符,如下所示。
OUPath=ABCD.COM/Test/All Users/India/Test/TestâOU/Desktop Users
Em Dash 打印为“â”。
我尝试使用以下命令转换 Powershell 的输出编码,但没有成功。
[Console]::OutputEncoding = [Text.Encoding]::Utf8
当前 Powershell 版本详细信息。
PS Codes> $PSVersionTable
Name Value
---- -----
PSVersion 5.1.19041.1
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.19041.1
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
默认输出编码如下:
PS Codes> [Console]::OutputEncoding
IsSingleByte : True
BodyName : IBM437
EncodingName : OEM United States
HeaderName : IBM437
WebName : IBM437
WindowsCodePage : 1252
IsBrowserDisplay : False
IsBrowserSave : False
IsMailNewsDisplay : False
IsMailNewsSave : False
EncoderFallback : System.Text.InternalEncoderBestFitFallback
DecoderFallback : System.Text.InternalDecoderBestFitFallback
IsReadOnly : True
CodePage : 437
我过去在这里回答过几个类似的问题(参见 https://whosebug.com/a/58542493/3156906 and https://whosebug.com/a/66404671/3156906),所以我 认为 这个问题是几个因素的组合: :
- 服务器正在发送一个编码为 utf-8 的响应,但是 没有 在
Content-Encoding
header - 在没有字符集的情况下,PowerShell 遵循 HTTP 规范并解码为 ISO-8859-1,最终会得到一个您正在逐字写入控制台的损坏的字符串
- Postman 可能检测到不知何故响应是 utf-8,即使没有字符集,并且正在解码响应流
当然,如果是一个字符集参数,那么这个答案的其余部分都是废话!
无论如何,这里有一段简单的脚本可以重现该问题:
# server encodes response text using utf8
PS> $text = "`u{2014}"; # em dash
PS> $bytes = [System.Text.Encoding]::UTF8.GetBytes($text);
PS> write-host $bytes;
226 128 148
# client (Invoke-RestMethod) decodes bytes as ISO-8859-1
PS> $text = [System.Text.Encoding]::GetEncoding("ISO-8859-1").GetString($bytes);
PS> write-host $text;
â
不幸的是,在您的情况下,处理是不可逆的,因为正如 @JosefZ 在评论中指出的那样,一些编码字节在以下情况下被“扼杀”(即丢弃)字节流被解码。
我能真正建议的是:
- 修复 API(如果您有访问权限),使其发送一个“charset=utf-8”参数,或者,
- 也许 hard-code 一些特殊处理可以在进行下游处理之前修复已知的错误名称
- 或者,使用
Invoke-RestMethod
的-OutFile
参数将响应字节写入文件而不对其进行解码,然后将其作为 utf-8 编码文件读回。
顺便说一句,这是我以前用来检测 encoding/decoding 对导致给定的修改的脚本 - 我每次都是从头开始写的,所以我也可以 post这次在这里,所以我可以稍后再找到它:-)。
$original = "`u{2014}"; # em dash
$mangled = "`u{00E2}"; # circumflex a
$encodings = [System.Text.Encoding]::GetEncodings() | sort-object -Property "Name";
foreach( $source in $encodings )
{
foreach( $target in $encodings )
{
$bytes = [System.Text.Encoding]::GetEncoding($source.Name).GetBytes($original);
$text = [System.Text.Encoding]::GetEncoding($target.Name).GetString($bytes);
if( $text -eq $mangled )
{
write-host "original string = '$original'";
write-host "mangled string = '$mangled'";
write-host " source encoding = '$($source.Name)'";
write-host " target encoding = '$($target.Name)'";
}
}
}