bash не может сохранить шестнадцатеричное значение 0x00 в переменной

man -a printf только по умолчанию man 1 на моей машине Linux Mint. whatis printf дает мне необходимую информацию.

11
25.02.2017, 05:41
4 ответа

Вы не можете сохранить нулевой байт в строке, потому что Bash использует строки в стиле C, которые резервируют нулевой байт для терминаторов. Таким образом, вам нужно переписать свой скрипт, чтобы просто передать последовательность, содержащую нулевой байт, без того, чтобы Bash сохранял ее посередине.Например, вы можете сделать это:

printf "\x36\xc9\xda\x00\xb4" | hd

Обратите внимание, кстати, что вам не нужен echo ; вы можете использовать printf Bash для решения многих других простых задач.

Или вместо связывания вы можете использовать временный файл:

printf "\x36\xc9\xda\x00\xb4" > /tmp/mysequence
hd /tmp/mysequence

Конечно, проблема заключается в том, что файл / tmp / mysequence может уже существовать. И теперь вам нужно продолжать создавать временные файлы и сохранять их пути в строках.

Или этого можно избежать, используя подстановку процесса:

hd <(printf "\x36\xc9\xda\x00\xb4")

Оператор <(команда) создает именованный канал в файловой системе, который будет получать выходные данные команды . hd получит в качестве своего первого аргумента путь к этому каналу, который он откроет и прочитает почти , как любой файл. Подробнее об этом можно прочитать здесь: https://unix.stackexchange.com/a/17117/136742 .

17
27.01.2020, 19:57

Вместо этого можно использовать zsh , который является единственной оболочкой, которая может хранить символ NUL в своих переменных. Этот символ даже находится в значении по умолчанию $ IFS в zsh .

nul=$'\0'

Или:

nul=$'\x0'

Или

nul=$'\u0000'

Или

nul=$(printf '\0')

Однако обратите внимание, что вы не можете передать такую ​​переменную в качестве аргумента или переменной среды команде, которая выполняется в качестве аргументов и среды. переменные - это строки с разделителями NUL, передаваемые системному вызову execve () (ограничение системного API, а не оболочки). Однако в zsh вы можете передавать байты NUL в качестве аргументов функциям или встроенным командам.

echo $'\0' # works
/bin/echo $'\0' # doesn't
9
27.01.2020, 19:57

Поскольку возврат каретки может быть частью имени файла, мне нравится использовать списки, заканчивающиеся нулем. Но я не могу хранить строку с нулевыми байтами, потому что bash, потому что Bash хранит строки как простые строки C, где нулевой байт является ограничителем строки и, следовательно, не может быть частью самой строки.

Чтобы обойти эту проблему, я создаю массив строк, где предполагается, что нулевой байт существует после каждого элемента. Сам список явно содержит нулевые байты. Я сохраняю значение, содержащее нулевые байты, в массиве, подобном этому...

    readarray -d $'\0' zArray < <(null_terminated_list_maker)

Затем я могу воспроизвести значение с нулевыми байтами следующим образом...

    [[ "${zArray[*]}" ]] && printf '%s\0' "${zArray[@]}"

Таким образом, массив bash можно использовать для хранения любого значения, содержащего нулевые байты.

Целью теста [[ "${zArray[*]}" ]]является проверка наличия в массиве каких-либо значений вообще (пустая строка является значением ). Тест решает проблему, когда если пустой массив передается в printf таким образом, то printf напечатает один нулевой байт, что неверно. Он не должен ничего печатать.

При представлении полностью произвольных данных возникает проблема. :Действительно ли ваш ввод заканчивался нулевым байтом? Этот метод необходимо расширить для обработки данных, которые могут заканчиваться или не заканчиваться нулевым байтом.

0
27.08.2021, 04:38

Bash использует внутренние строки C, которые не могут хранить нулевой байт. Сохраните значение во временном файле, подобном этому:

    zHex=$(mktemp --tmpdir "$(basename "$0")-XXXX")
    trap "rm -f ${zHex@Q}" EXIT

Переменная zHex теперь содержит уникальное имя файла. Файл, на который ссылается $zHex, можно удалить вручную, но он будет автоматически удален, когда программа по какой-либо причине завершится.

Затем используйте переменную следующим образом:

    echo -ne "\x36\xc9\xda\x00\xb4" > "$zHex"
    hd "$zHex"

Это НЕ сохраняет значение с нулевыми байтами в переменной. Вместо этого он использует переменную для хранения имени файла. Файл, как и любой другой файл, может содержать нулевые байты и может использоваться снова и снова. Сам файл, скорее всего, никогда не будет физически записан на диск.

Через ловушку bash автоматически удаляет файл, поэтому вам не нужно беспокоиться об удалении его вручную, если только вы не создаете сумасшедший массив мусора. Из-за буферизации ОЗУ этот метод работает достаточно быстро.

1
31.08.2021, 22:41

Теги

Похожие вопросы