Преобразование многобайтовых символов 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"
Другие вопросы по тегам