Редактирование двоичных потоков, содержащих байты \ x00

8

Используя только инструменты оболочки, как можно редактировать двоичный поток, содержащий NULL (0x00 символов), сохраняя 0x00 символов в выходном потоке?

При редактировании необходимо заменить символ в указанной позиции на другой символ (в следующем примере символом '|'), например:

dd ibs=1 skip=$offset count=$reglen status=none if=$ARQ |
        sed 's/./\|/2' |
        sed 's/./\|/5' #| more replacements....

Но sed удаляет все символы \ 0x00 перед заменой.

РЕДАКТИРОВАТЬ - Демонстрация поведения sed в моей среде с помощью теста @George Vasiliou:

$ echo -e "lineA\nlineB\nlineC" | tr '\n' '\0' | od -t x1
0000000 6c 69 6e 65 41 00 6c 69 6e 65 42 00 6c 69 6e 65
0000020 43 00
0000022

$ echo -e "lineA\nlineB\nlineC" | tr '\n' '\0' | sed 's/./|/5' | od -t x1
0000000 6c 69 6e 65 7c 6c 69 6e 65 42 6c 69 6e 65 43
0000017

Моя среда - AIX 7.1, а sed - не версия gnu.

Лучано
источник

Ответы:

10

sedэто текстовая утилита Он работает с текстовыми строками (последовательностями не NUL-символов (не байтов) ограниченной длины, разделенными символом новой строки).

Если вы хотите изменить 2- й и 5- й байты последовательности байтов, это не сработает по нескольким причинам:

  • sedработает над текстом. Если ввод содержит NUL-символы, не заканчивается символом новой строки, содержит более двух байтов LINE_MAX между двумя символами новой строки, содержит последовательности байтов, которые не образуют допустимых символов, в зависимости от sedреализации, он не будет работать при все. (обратите внимание, что GNU sedне имеет многих из этих ограничений).
  • даже если этот двоичный ввод образует правильный текст, .соответствует символам, а не байтам, поэтому может соответствовать более одного байта.
  • поскольку код sed запускается для каждой строки ввода, это будет изменять второй и пятый символ каждой строки, а не всего ввода.

Для обработки ввода как произвольных массивов байтов (без ограничения байтов NUL или ограничений длины) вы можете использовать perlвместо этого:

 dd.... | perl -0777 -pe 'for $o (1, 4) {substr($_, $o, 1) = "|"}'

Пример:

$ printf 'a\0b\0cd' |
>   perl -0777 -pe 'for $o (1, 4) {substr($_, $o, 1) = "|"}' |
>   od -Ax -tx1 -tc
000000  61  7c  62  00  7c  64
         a   |   b  \0   |   d
000006

Или вы могли бы использовать промежуточное текстовое представление, как с помощью vim«s xxdпомощника:

dd... | xxd -p | sed '1s/../7c/2;1s/../7c/5' | xxd -p -r

xxd -pпо умолчанию дает шестнадцатеричный дамп с 60 символами в строке. Выше мы заменяем второй и пятый двухзначный шестнадцатеричный гекс первой строки 7cна номер для ASCII |.

Стефан Шазелас
источник
Спасибо. Я создавал обходной путь, используя xxd. Большой ! Оба решения работали в AIX.
Лучано
1

Ты уверен ? с помощью простого теста это, кажется, не происходит в моем случае (gnu sed 4.2.2)

$ echo -e "lineA\nlineB\nlineC"
lineA
lineB
lineC
$ echo -e "lineA\nlineB\nlineC" |tr '\n' '\0'
lineAlineBlineC
$ echo -e "lineA\nlineB\nlineC" |tr '\n' '\0' |sed 's/./|/5'
line|lineBlineC
# Verification if the nulls are still there:
$ echo -e "lineA\nlineB\nlineC" |tr '\n' '\0' |sed 's/./|/5' |tr '\0' '\n'                                                                                                
line|
lineB
lineC

При дальнейшем тестировании ноль будет потерян, если вы замените 6-й символ в моих тестах (нулевая позиция):

$ echo -e "lineA\nlineB\nlineC" |tr '\n' '\0' |sed 's/./|/6' |tr '\0' '\n'
lineA|lineB 
lineC

$ echo -e "lineA\nlineB\nlineC" |tr '\n' '\0' |sed 's/./|/7' |tr '\0' '\n'
lineA
|ineB           
lineC 
Георгий Васильев
источник
@Luciano Смотрите обновление
Джордж Василиу
Посмотрите на мои правки
Лучано
@Luciano, я также попробовал с sed --posix, который согласно моему руководству отключает все расширения GNU, но все еще присутствуют нулевые байты ....
Джордж Василиу
Я пробовал sed в Linux, и да, похоже, работает. Но мне нужно, чтобы он работал в AIX.
Лучано
1
@Luciano, конечно, я могу понять это ... К сожалению, у меня нет AIX, чтобы помочь вам, и, насколько я знаю, кажется, что нет онлайн-оболочек AIX, чтобы играть с ... Я уверен, что ответ Мистер Чазелас поможет вам.
Георгий
0

Попробуйте клон bbe - sed для двоичных потоков: https://sourceforge.net/projects/bbe/

user280267
источник
Не могли бы вы добавить некоторые вспомогательные сведения, например, как пользователь в своей среде AIX может использовать его? Также обратите внимание, что в вопросе написано «Использование только инструментов оболочки», поэтому им может быть запрещено компилировать / устанавливать дополнительные инструменты,
Джефф Шаллер
Вы уверены, что ссылаетесь на правильный инструмент? Ваша ссылка переходит на проект «Блочное шифрование» (2Bx4Bx2B), последний раз обновленный в 2013 году
Ale