При отладке программ, которые работают с бинарными данными, часто нужно вывести содержимое строки на экран, причём желательно в виде шестнадцатеричной строки.
Для этого можно использовать следующую небольшую функцию hex.
local function hex(s)
return s:gsub(".", function(c)
return ("%02x "):format(c:byte())
end):sub(1, -2)
end
print(hex("\x01\x23\x45\x67\x89\xab\xcd\xef"))
--> 01 23 45 67 89 ab cd ef
Чтобы понять, как оно работает, нужно понимать, что для всех строк установлена
метатаблица с полем __index, ссылающееся на string. Таким образом, для
строки s запись s.sub(s, 1, 2) эквивалентна string.sub(s, 1, 2).
Так как первым аргументом метода строки передаётся сама строка, то можно
сократить s.sub(s, 1, 2) до s:sub(1, 2).
Строковые литералы (строк, записанных прямо в коде, вроде "hey") также
являются строками, поэтому у них также можно вызвать функции string. Однако
напрямую индексировать литерал (в смысле, писать "test":sub(1, 2)) нельзя —
это будет синтаксической ошибкой. Литерал нужно обернуть в скобки:
("test"):sub(1, 2) — эквивалентно string.sub("test", 1, 2), но короче.
Мы используем функцию string.gsub, передав шаблон "." (любой символ) и
функцию. Функция будет вызываться для каждого символа и менять его на то,
что она вернёт.
С помощью string.byte (c:byte()) мы получаем числовое значение байта. Затем
передаём его в string.format с форматом "%02x ". %x конвертирует число в
шестнадцатеричное, %02x также дополняет число слева нулямм до тех пор, пока
длина его не будет равна двум (число 14 превращает в 0e, например). После
каждого символа добавляем пробел.
Наконец, убираем в конце лишний пробел после последнего символа с помощью
string.sub и возвращаем полученную строку.