解码或转义 \u00f0\u009f\u0091\u008d 为 👍

问题描述 投票:0回答:4

我们都知道 UTF-8 很难。我从 Facebook 导出消息,生成的 JSON 文件将所有非 ASCII 字符转义为 unicode 代码点。

我正在寻找一种简单的方法来将这些 unicode 代码点转义为常规的旧 UTF-8。我也很想使用 PowerShell。

我试过了

$str = "\u00f0\u009f\u0091\u008d"
[Regex]::Replace($str, "\\[Uu]([0-9A-Fa-f]{4})", `
{[char]::ToString([Convert]::ToInt32($args[0].Groups[1].Value, 16))} )

但这只会给我 ð 结果,而不是 👍。

我也尝试使用 Notepad++,我发现了这篇文章:How to conversion escaped Unicode (e.g.

\u0432\u0441\u0435
) to UTF-8 chars (все) in Notepad++。接受的答案也与上面的示例完全相同:ð

我在这里找到了解码解决方案:UTF8.js库可以完美解码文本,您可以在这里尝试一下(使用

\u00f0\u009f\u0091\u008d
作为输入)。

PowerShell中有没有办法解码

\u00f0\u009f\u0091\u008d
来接收👍?我希望在导出的 Facebook 消息中包含真正的 UTF-8,这样我就可以真正阅读它们。

帮助我理解

\u00f0\u009f\u0091\u008d
实际代表什么(除了它是 一些 UTF-8 十六进制表示)的奖励积分。为什么它与 C++ 中的
U+1F44D
\uD83D\uDC4D
相同?

json facebook powershell utf-8 facebook-messenger
4个回答
9
投票

👍字符的 Unicode 代码点是

U+1F44D

使用可变长度 UTF-8 编码,需要以下 4 字节(以十六进制数字表示)来表示此代码点:

F0 9F 91 8D
.

虽然这些字节在您的字符串中是可识别的,

$str = "\u00f0\u009f\u0091\u008d"

它们不应该被表示为

\u
转义码,因为它们不是Unicode代码单元/代码点,它们是字节

使用 4 十六进制数字转义序列 (UTF-16),正确的表示需要 2 16 位 Unicode 代码 units,即所谓的代理对,它们一起表示单个非 BMP 代码

U+1F44D

$str = "\uD83D\uDC4D"

如果您的 JSON 输入使用了正确的 Unicode 转义,PowerShell 将正确处理该字符串;例如:

'{ "str": "\uD83D\uDC4D" }' | ConvertFrom-Json > out.txt

如果您检查文件

out.txt
,您会看到类似以下内容:

str
---
👍 

(输出被发送到文件,因为控制台窗口无法正确渲染 👍char.,至少在没有额外配置的情况下是这样;但是请注意,如果您在 Linux 或 macOS 上使用 PowerShell Core,终端输出将起作用.)


因此,最好的解决方案是从源头上纠正问题并使用正确的 Unicode 转义(或者甚至使用字符本身,只要源支持任何标准 Unicode 编码)。

如果您确实必须解析损坏的表示,请尝试以下解决方法(PSv4+),建立在您自己的

[regex]::Replace()
技术之上:

$str = "A \u00f0\u009f\u0091\u008d for Mot\u00c3\u00b6rhead."

[regex]::replace($str, '(?:\\u[0-9a-f]{4})+', { param($m) 
  $utf8Bytes = (-split ($m.Value -replace '\\u([0-9a-f]{4})', '0x$1 ')).ForEach([byte])
  [text.encoding]::utf8.GetString($utf8Bytes)
})

这应该会产生

A 👍 for Motörhead.

上面将

\u...
转义序列转换为它们表示的字节值,并将生成的字节数组解释为 UTF-8 文本。


要将解码后的字符串保存到 UTF-8 文件,请使用 ... | Set-Content -Encoding utf8 out.txt



或者,在 PSv5+ 中,正如 Dennis 本人所建议的,您可以创建

Out-File

,因此它是虚拟别名,
>
default 通过 PowerShell 的全局参数默认值哈希表转换为 UTF-8:

$PSDefaultParameterValues['Out-File:Encoding'] = 'utf8'

但请注意,在 Windows PowerShell(而不是 PowerShell

Core)上,在这两种情况下您都会获得一个带有 BOM 的 UTF-8 文件 - 避免这种情况需要直接使用 .NET 框架:请参阅使用PowerShell 以 UTF-8 格式写入不带 BOM 的文件


1
投票

$text=[regex]::Unescape("A \u00f0\u009f\u0091\u008d for Mot\u00c3\u00b6rhead.") Write-Host "[regex]::Unescape(utf-8) = $text" $encTo=[System.Text.Encoding]::GetEncoding('iso-8859-1') # Change it to yours (iso-8859-2) i suppose $bytes = $encTo.GetBytes($Text) $text=[System.Text.Encoding]::UTF8.GetString($bytes) Write-Host "utf8_DecodedFrom_8859_1 = $text"

[正则表达式]::Unescape(utf-8) = A ð 代表 Motörhead。

utf8_DecodedFrom_8859_1 = A 👍 代表 Motörhead。


1
投票

不好的是——队伍会很长。 (前 2 个半字节“00”是浪费)

我必须承认,mklement0 的例子很迷人。

编码代码——只有一行!!!:

$emoji='A 👍 for Motörhead.' [Reflection.Assembly]::LoadWithPartialName("System.Web") | Out-Null $str=(([System.Web.HttpUtility]::UrlEncode($emoji)) -replace '%','\u00') -replace '\+',' ' $str

您可以通过标准 url 方式对其进行解码:

$str="A \u00f0\u009f\u0091\u008d for Mot\u00c3\u00b6rhead." $str=$str -replace '\\u00','%' [Reflection.Assembly]::LoadWithPartialName("System.Web") | Out-Null [System.Web.HttpUtility]::UrlDecode($str)

Motörhead 的 👍。


0
投票

© www.soinside.com 2019 - 2024. All rights reserved.