#bash
Вопрос:
Есть ли какой-нибудь однострочный bash, который позволил бы мне разбивать двоичные данные, поступающие из канала, на строки?
В качестве примера:
$ echo -ne 'x31x00x32rnx33x34x35x00rn' | xxd
Это приводит к:
00000000: 3100 320d 0a33 3435 000d 0a 1.2..345...
И я хотел бы иметь:
00000000: 3100 320d 0a 1.2..
00000005: 3334 3500 0d0a 345...
В случае, если двоичные данные содержат новую строку, я не возражаю, что сообщение будет разделено на две или более строк (в моем случае это произойдет редко).
У меня много устройств в этой области, и необходимость отправлять сценарии или программы для этого была бы громоздкой. Сообщения имеют переменный размер, поэтому xxd -c
будут работать только для некоторых сообщений.
Я попытался передать сообщения по конвейеру read
, что правильно разбивает сообщение на строки. Но по какой-то причине (вероятно, сам баш) нули удаляются из моих сообщений:
echo -ne 'x31x00x32rnx33x34x35x00rn' | while read; do echo "$REPLY" | xxd; done
00000000: 3132 0d0a 12..
00000000: 3334 350d 0a 345..
(ПРАВКА: смещения байтов могут быть равны нулю, это не проблема. Проблема в этом последнем примере заключается в отсутствующих нулях в части данных.)
Может быть, есть способ сохранить нули при использовании read
? Или, может быть, мой вариант использования слишком волосатый?
Комментарии:
1. Вам нужно смещение байта слева, как в вашем первом примере? В
read
примере xxd работает только на отдельных строках, поэтому вы теряете смещения слева.2. Я придерживаюсь менталитета «если этого не существует, то создайте его сами». Хотя я не уверен, что bash может сделать то, о чем вы просите изначально (по крайней мере, без какого-либо фанкового синтаксиса), я уверен, что вы могли бы создать простое решение на выбранном вами языке и вызвать свое решение из bash. Мне на ум приходит Python (предпочтение). Вы не возражаете против решения на Python, которое можно вызвать из вашей оболочки?
3. Вы можете довольно близко сойтись с:
printf 'x31x00x32rnx33x34x35x00rn' | perl -ne 'printf "d: ", $c; print unpack("H* ", "$_") . "n"; $c = length'
4. @JardelLucca возможно, лучшее в bash или любой командной оболочке то, что она предназначена для взаимодействия с другими программами, включая программы, которые вы написали сами. Просто передайте данные в пользовательскую программу, предназначенную для выполнения того, что вы, что все равно будет выглядеть очень элегантно в bash. Создание гораздо более крупной команды (которая все еще технически вызывает другие программы), безусловно, должно сработать, но это будет менее элегантно. Когда я говорю здесь «элегантный», я имею в виду простоту использования и удобочитаемость.
5. @JardelLucca на самом деле, ваше второе решение
echo -ne 'x31x00x32rnx33x34x35x00rn' | while read; do echo "$REPLY" | xxd; done
работает для меня. Я использую zsh. Возможно, рассмотрим новую оболочку 🙂
Ответ №1:
Вы можете получить 90% того, что хотите, с помощью:
$ printf 'x31x00x32rnx33x34x35x00rn' |
perl -nE 'printf "d: ", $c; say unpack("H*", "$_") ; $c = length'
00000000: 3100320d0a
00000005: 333435000d0a
Комментарии:
1. Вот еще одна причина перестать откладывать и сразу начать изучать perl : )