Переменная с разделителем NUL

Переменная с разделителем NUL

GNU bash, версия 4.4.19(1)-релиз (x86_64-pc-linux-gnu)

Идея заключается в том, чтобы установить переменную в набор данных, разделенный NUL. Здесь$samples

Однако это приводит к:

предупреждение: подстановка команды: проигнорирован нулевой байт во входных данных

при выполнении:

samples="$(find . -type d -iregex './sample[0-9][0-9]' -printf "%f\0" | sort -z)"

Я подумал, что могу повторно использовать эту переменную, так как мне нужно повторять одни и те же значения несколько раз:

while IFS= read -rd '' sample; do
    echo $sample
done<<< "$samples"

Я мог бы использовать \nэто \0внаходитькоманда в этом конкретном случае, но хотелось бы знать, как, если это вообще возможно, сделать это с разделителем NUL.

По желанию я могу сделать:

while IFS= read -rd '' sample; do
    echo $sample
done< <(find . -type d -iregex './E[0-9][0-9]' -printf "%f\0" | sort -z)

но - поскольку мне нужно выполнить цикл несколько раз, это приводит к очень избыточному коду - и мне пришлось бы запуститьнаходитьиСортироватькоманду каждый раз.

Может быть, преобразовать результат в массив?


  • Это возможно?
  • Почему данные, разделенные NUL, нельзя использовать как есть?

решение1

Фактом является то, что вы не можете хранить \0нулевые байты в контексте строки bash из-за базовой реализации C. См.Почему $'\0' или $'\x0' - пустая строка? Должен быть нулевым символом, не так ли?.

Одним из вариантов было бы удаление нулевых байтов после команды сортировки в конце конвейера с использованием trи сохранением результата для решения немедленной проблемы выдаваемого предупреждающего сообщения. Но это все равно оставило бы вашу логику несовершенной, поскольку имена файлов с переводами строк все равно были бы сломаны.

Используйте массив, команду mapfileor readarray(в bash 4.4+) для непосредственного получения результатов из findкоманды

IFS= readarray -t -d '' samples < <(find . -type d -iregex './sample[0-9][0-9]' -printf "%f\0" | sort -z)

решение2

Оболочка bashне поддерживает то, что вы хотите сделать. zshОболочка поддерживает из коробки.

% mkdir sample11 SAMple12 sample21 sample22 dir1
% ll
total 20
drwxrwxr-x 2 fpm fpm 4096 Jun  9 13:46 dir1
drwxrwxr-x 2 fpm fpm 4096 Jun  9 13:46 sample11
drwxrwxr-x 2 fpm fpm 4096 Jun  9 13:46 SAMple12
drwxrwxr-x 2 fpm fpm 4096 Jun  9 13:46 sample21
drwxrwxr-x 2 fpm fpm 4096 Jun  9 13:46 sample22
% samples=$(find . -type d -iregex './sample[0-9][0-9]' -print0 | sort -z)
% echo $samples
./sample11./SAMple12./sample21./sample22
% echo $samples | od -a
0000000   .   /   s   a   m   p   l   e   1   1 nul   .   /   S   A   M
0000020   p   l   e   1   2 nul   .   /   s   a   m   p   l   e   2   1
0000040 nul   .   /   s   a   m   p   l   e   2   2 nul  nl
0000055
%

Связанный контент