Преобразование многобайтовых символов UTF-8 в несколько символов ascii
Может ли кто-нибудь помочь мне с преобразованием некоторых (потенциальных) поддельных многобайтовых символов UTF-8 в ascii следующим образом?
\u6162
→ ["\x61", "\x62"]
→ ["a", "b"]
→ "ab"
Мой вариант использования только для удовольствия. Я знаю, что я ничего не сжимаю, представляя два символа ascii в многобайтовом символе.
Я играл с различными версиями unpack
но это никогда не работает правильно:
"\u6162".unpack('H*')
# => ["e685a2"]
Кажется, что принудительное кодирование возвращает то же самое:
"\u6162".force_encoding('US-ASCII')
# => "\xE6\x85\xA2"
2 ответа
"\u6162"
не эквивалентно "\x61" + "\x62"
, \u
указывает кодовую точку Unicode, которая не переводится непосредственно в шестнадцатеричное значение. Кодовая точка Unicode 6162 - это 慢.
Поскольку это строка и поскольку Ruby по умолчанию использует UTF-8, при распаковке вы получите значение UTF-8 U + 6162, которое составляет три байта: E6 85 A2
,
2.2.1 :023 > "\u6162".encoding
=> #<Encoding:UTF-8>
2.2.1 :024 > "\u6162".unpack("A*")
=> ["\xE6\x85\xA2"]
Чтобы получить то, что вы хотите, вам нужно его представление UTF-16 61 62
, Но если вы просто закодировать как UTF-16
вы получите маркер порядка байтов FE FF 61 62
, Так что используйте UTF-16BE (big endian), чтобы избежать этого.
2.2.1 :052 > "\u6162".encode("UTF-16BE").unpack("A*")
=> ["ab"]
"\u6162".codepoints.first.divmod(16 ** 2).map(&:chr).join
# => "ab"