#bash #xxd
#bash #xxd
Вопрос:
Итак, мне было интересно, как удалить номера строк и ascii при выводе данных с помощью xxd.
Код:
chst1="$(xxd -u -p -l1 -s 765 "$d2s")"
chst2="$(xxd -u -p -l1 -s 766 "$d2s")"
chst3="$(xxd -u -p -l1 -s 767 "$d2s")"
chst4="$(xxd -u -p -l1 -s 768 "$d2s")"
chst5="$(xxd -u -p -l1 -s 769 "$d2s")"
chst6="$(xxd -u -p -l1 -s 770 "$d2s")"
chst7="$(xxd -u -p -l1 -s 771 "$d2s")"
chst8="$(xxd -u -p -l1 -s 772 "$d2s")"
chst9="$(xxd -u -p -l1 -s 773 "$d2s")"
echo "Hex"
echo " $chst1 $chst2 $chst3 $chst4 $chst5 $chst6 $chst7 $chst8 $chst9 "
echo "Binary"
echo " $chst1 $chst2 $chst3 $chst4 $chst5 $chst6 $chst7 $chst8 $chst9 " | xxd -r -p | xxd -b
Который выводит
Hex
67 66 00 28 08 F0 80 80 0C
Binary
00000000: 01100111 01100110 00000000 00101000 00001000 11110000 gf.(..
00000006: 10000000 10000000 00001100 ...
Но я хочу 00000000: и 00000006: и gf.(.. и … удален из выходных данных.
Что касается количества переменных, это правильно и некрасиво, но это единственное реально работающее решение, которое у меня есть, поскольку каждая из них сама по себе является переменной в коде.
Комментарии:
1. Что в
d2s
? Что вы пробовали? С Awk это должно быть тривиально, но ваш код выглядит так, как будто он нуждается в более радикальном рефакторинге. Все, что содержит подобные повторяющиеся замены команд, пахнет подозрительно.2. lol. d2s — это файл сохранения игры Diablo. Там есть такие вещи, как уровень, имя персонажа, статистика, такая как сила, жизнеспособность и так далее. Эта часть скрипта будет считывать данные статистики, чтобы я мог показать это в своем терминале при выборе символа. Который, в свою очередь, является частью более крупного (уже работающего скрипта), который позволяет мне выбрать персонажа, переместить его в официальную папку сохранения и поиграть с ним. Почему? Более 50 символов в игре затрудняют поиск в меню выбора игрового персонажа… жуткий, временами он даже падал на меня.
3. Кроме того, echo шестнадцатеричного и двоичного кода — это просто тест, чтобы показать, как это выглядит. В конце они будут просто преобразованы в данные, которые я хочу извлечь (показать в терминале), и echo в том виде, в каком они отображаются в данный момент, будут удалены. Итак, на данный момент это тестирование, и цель — объяснить, что я вижу.
Ответ №1:
В Bash встроена вполне приличная базовая арифметика. Но я также не вижу необходимости извлекать шестнадцатеричные цифры одну за другой.
echo Hex:
xxd -u -p -l 9 -s 765 "$d2s" | sed 's/../ amp;/g'
echo Bin:
xxd -u -b -l 9 -s 765 "$d2s" | cut -c 11-65
Если вы действительно настаиваете на извлечении байтов один за другим (возможно, на самом деле они имеют разные непоследовательные смещения?) вы могли бы собрать значения в два массива.
hex=()
bin=()
for offset in 123 234 345 456; do
hex =("$(xxd -p -s "$offset" -l 1 -u "$d2s")")
bin =("$(xxd -b -s "$offset" -l 1 "$d2s" | awk '{ print $2 }')")
done
echo Hex:
printf " %s" "${hex[@]}"
printf "n"
echo Bin:
printf " %s" "${bin[@]}"
printf "n"
В основном для разнообразия, это демонстрирует, как использовать Awk. Обычно я бы выбрал cut
для простого извлечения, когда вы знаете, как далеко в каждой строке вы хотите зайти, но Awk определенно более универсален. Это работает очень хорошо, когда смещения подстрок не обязательно фиксированы, но вы знаете, сколько полей в каждой строке.
Параллельные массивы также удобны, если вы хотите связать метку с каждым байтом. Возможно
labels=(Hunger Thirst "Need to pee" Arms Legs Velocity Strength)
...
for ((i=0; i<=${#labels[@]}; i)); do
echo "${labels[i]}: ${hex[i]} (${bin[i]})"
done
Комментарии:
1. Как уже показано в моем скрипте. Действительно, они имеют разные смещения. Итак, длина в 1 бит со смещением 765, затем 766 и т.д. (и поверьте мне, это становится еще хуже, чем это, хаха). Но спасибо за вашу помощь, это избавило меня от кучи кодирования, как я вижу из вашего кода. ^_^ Что касается битов. Каждый из них содержит значение. Пример: Сила: 40, ловкость: 56, Энергия: 83 и т.д. Это для визуального отображения данных, представленных этими значениями.
2. Ваш код выглядит так, как будто байты следуют друг за другом; но массив должен работать, если у вас есть коллекция непоследовательных смещений, из которых вы хотите выделить один байт. (Только что исправлена опечатка в коде, извините.)
3. Да, я собираюсь поработать над вашим кодом сегодня вечером. Спасибо, чувак. ^_^ Редактировать: Что, если я захочу изменить длину битов? допустим, мне нужна длина в 4 бита. Могу ли я затем добавить для смещения в 123 234 345 456; для длины в 14; сделать?? Может ли это быть так просто, и я слишком много думаю?
4. Не уверен, что вы имеете в виду. Вы хотите извлечь старшую и младшую части байта отдельно?
5. С помощью Awk
substr($1, 1, 4)
получает первые четыре символа первого поля. Из шестнадцатеричных цифр каждая цифра представляет собой nybble. Сxxd
невозможно получить меньше одного байта.
Ответ №2:
и добро пожаловать в SO!
Во-первых, давайте не будем порождать так много избыточных процессов.
xxd -u -p -l9 -s 765 "$d2s" |
perl -ne 'for my $o (0..16) { next if $o%2; printf "b ", substr($_,$o,2) }'
01000011 01000010 00000000 00011100 00001000 00000000 01010000 01010000 00000000
Я не добавлял новую строку, но мы могли бы.
Если у вас их нет perl
(идите и получите их!), то
for offset in {0..16}
do (( offset%2)) amp;amp; continue
printf "d " $(bc <<< "ibase=16;obase=2;${sample:$offset:2}")
done
01100111 01100110 00000000 00101000 00001000 11110000 10000000 10000000 00001100
Опять же, нет новых строк, но вы, кажется, в состоянии это понять… но теперь мы снова создаем кучу процедур. Вместо этого используйте tripleee cut
.
Дайте мне знать, если вам нужны дополнительные подробности.
Комментарии:
1. Спасибо. Я установлю Perl. Что касается перевода строк. Да, они необходимы. Пример: Сила: 40, ловкость: 56, Энергия: 83 и т.д. Это для визуального отображения данных, представленных этими значениями.
2. В наши дни Perl должен быть стандартом де-факто на большинстве платформ, если только вы не используете что-то действительно ограниченное, например Busybox (или что-то действительно глупое, например Windows).
3. Да, я это заметил. Я никогда не использовал это и в основном начал несколько недель назад с написания сценариев на bash. Я запускаю Debian 10, в нем установлен perl 5, версия 28.
4. Я начал изучать learning
awk
примерно год назад, поскольку он так широко используется. Я начал использоватьperl
в первой системе unix, над которой работал пару десятилетий назад, и после этого не видел в этом смысла… Мне еще предстоит найти что-нибудь,awk
чтоperl
не будет, хотя, по общему признанию, иногда приятно не добавлять параметры командной строки, чтобы попасть туда.5. «Что касается перевода строк. Да, они необходимы.» Где?