Пропуск каждого другого символа тривиален для таких инструментов, как sed или awk, если вам не нужно справляться с символами новой строки и нулевыми байтами.Но поддержка Busybox для нулевых байтов в sed и awk достаточно слабая, поэтому я не думаю, что вы вообще справитесь с ними.Можно работать с символами новой строки, но это огромная боль, потому что приходится иметь дело с 16 различными комбинациями в зависимости от того, является ли каждая позиция в 4-байтовом блоке новой строкой или нет.
Поскольку произвольные двоичные данные являютсяболь, давайте переведем на шестнадцатеричный или восьмеричный!Я черпаю вдохновение из сценариев bin2hex
и hex2bin
Стефана Шазеласа .Поскольку нам не важен промежуточный формат, я буду использовать восьмеричный, с которым гораздо проще иметь дело, потому что на последнем шаге используется printf
, который поддерживает только восьмеричный.hex2bin
Стефана использует awk для шестнадцатеричного преобразования в восьмеричное;oct2bin
может использовать sed.Итак, в конце вам понадобятся sh
, od
, sed
и printf
.Я не думаю, что вы можете избежать printf
: это важно для вывода нулевых байтов.* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * od
является существенным, большинство его опций - нет, поэтому должна быть возможность настроить этот код для поддержки очень урезанного кода с немного большей постобработкой.
od -An -v -t o1 -w4 |
sed 's/^ \([0-7]*\) \([0-7]*\).*/printf \\\\\1\\\\\2/' |
sh
Причина этогопо сравнению с вашим подходом, основанным на dd, настолько быстро, что BusyBox запускает printf
в родительском процессе, тогда как dd
требует своего собственного процессаФоркинг медленный.Если я правильно помню, есть опция компиляции, которая делает BusyBox форком для всех утилит.В этом случае мой подход, вероятно, будет таким же медленным, как и ваш.Вот промежуточный подход, использующий dd
, который не может избежать разветвлений, но, по крайней мере, избегает открытия и закрытия файла каждый раз.Это должно быть немного быстрее, чем у вас.
i=$(($(wc -c <"$1") / 4))
exec <"$1"
dd ibs=2 count=1 conv=notrunc 2>/dev/null
while [ $i -gt 1 ]; do
dd ibs=2 count=1 skip=1 conv=notrunc 2>/dev/null
i=$((i - 1))
done