У меня есть строка:
"61 62 63 64 65 67 69 69 6a
"
, который я хочу интерпретировать как шестнадцатеричные значения и отображать их как символы ASCII (эти значения должны воспроизводить строку символов "abcdefghij").
Обычно я пытаюсь написать что-то быстрое, как это:
$ echo "61 62 63 64 65 67 69 69 6a" | perl -ne 'print "$_"; print pack("H2 "x10, $_)."\n";'
61 62 63 64 65 67 69 69 6a
a
... а потом я удивляюсь, почему я получаю только один символ назад :)
Во-первых, позвольте мне отметить, что строка, которую я имею, также может быть представлена в виде шестнадцатеричных значений байтов, которые она занимает в памяти:
$ echo -n "61 62 63 64 65 67 68 69 6a" | hexdump -C
00000000 36 31 20 36 32 20 36 33 20 36 34 20 36 35 20 36 |61 62 63 64 65 6|
00000010 37 20 36 38 20 36 39 20 36 61 |7 68 69 6a|
0000001a
_ ( NB. По сути, я хочу «преобразовать» указанные выше значения байтов в памяти в качестве входных данных в указанные ниже значения при просмотре с помощью hexdump:
$ echo -n "abcdefghij" | hexdump -C
00000000 61 62 63 64 65 66 67 68 69 6a |abcdefghij|
0000000a
... так были получены исходные значения для входной шестнадцатеричной строки.
) _
Что ж, этот учебник по распаковке / распаковке (AKA Как система хранит данные ) оказывается самым полезным для меня, так как упоминает:
Функция pack принимает строку шаблона и список значений [...]
$rec = pack( "l i Z32 s2", time, $emp_id, $item, $quan, $urgent);
Возвращает скаляр, содержащий список значений, сохраненных в соответствии с форматами, указанными в шаблоне [...]
$rec
будет содержать следующее (первая строка в десятичном виде, вторая в шестнадцатеричном, третья в качестве символов, где это применимо). Символы трубы обозначают границы полей.
Offset Contents (increasing addresses left to right)
0 160 44 19 62| 41 82 3 0| 98 111 120 101 115 32 111 102
A0 2C 13 3E| 29 52 03 00| 62 6f 78 65 73 20 6f 66
| b o x e s o f
То есть, в моем случае $_
является одиночной строковой переменной - тогда как pack
ожидает в качестве входных данных список нескольких таких «одиночных» переменных (в дополнение к строке шаблона форматирования); и выводит снова «единственную» переменную (которая, однако, может быть значительным объемом памяти!). В моем случае, если выходная переменная 'single' содержит код ASCII в каждом байте в памяти, тогда я полностью настроен (тогда я мог бы просто напечатать выходную переменную напрямую).
Таким образом, чтобы получить список переменных из строки $_
, я могу просто split
указать его на пробел - однако, обратите внимание:
$ echo "61 62 63 64 65 67 68 69 6a" | perl -ne 'print "$_"; print pack("H2", split(/ /, $_))."\n";'
61 62 63 64 65 67 68 69 6a
a
... необходимо указать количество элементов, равное pack
ed (иначе мы снова получим только один символ); тогда любая из этих альтернатив работает:
$ echo "61 62 63 64 65 67 68 69 6a" | perl -ne 'print "$_"; print pack("H2"x10, split(/ /, $_))."\n";'
61 62 63 64 65 67 68 69 6a
abcdeghij
$ echo "61 62 63 64 65 67 68 69 6a" | perl -ne 'print "$_"; print pack("(H2)*", split(/ /, $_))."\n";'
61 62 63 64 65 67 68 69 6a
abcdeghij