Представление/цитирование NUL в командной строке

Представление/цитирование NUL в командной строке

Можно ли \0использовать в командной строке?

Фон

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

perl -e 'print pack ("c*",1..255,10)' | parallel -k echo | md5sum
d03484ca75b3e38be411198d66bf4611  -
perl -e 'print pack ("c*",1..255,10)' | md5sum
d03484ca75b3e38be411198d66bf4611  -

Но, \0похоже, это сложно (здесь показано с помощью A\0B\n):

perl -e 'print pack ("c*",65,0,66,10)' | wc -c
4 (A\0B\n)
perl -e 'print pack ("c*",65,0,66,10)' | parallel echo | wc -c
2 (A\n)
perl -e 'print pack ("c*",65,0,66,10)' | parallel --dry-run echo | wc -c
9 (echo A\0B\n)
perl -e 'print "echo ",pack ("c*",65,0,66,10)' | bash | wc -c
3 (AB\n)

Я могу как-то обосновать второй пример: \0может быть интерпретирован как EOS, но тогда это также должно быть в случае примера 4. Пример 3 подчеркивает, что GNU Parallel не видит \0как EOS, а передает его в bash.

Можете ли вы объяснить, что происходит? Особенно меня озадачивает случай 4.

И что еще важнее:

Есть ли способ заключить \0командную строку в кавычки, чтобы eg echoее увидел?

решение1

При выполнении команды список аргументов представляет собой список указателей на строки с символом NUL в конце, переданные execve()системному вызову (точно так же, как переменные окружения, которые представляют собой другой список строк с символом NUL в конце, переданных системному вызову execve()).

В результате аргументы и переменные окруженияказненкоманды не могут содержать символ NUL.

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

Вы можете передавать данные с символами NUL через stdin (или любой другой файловый дескриптор) или в любом типе файла. Или некоторые команды понимают некоторую форму кодирования.

Например, совместимые с UNIX echoреализации понимают \0(два символа обратная косая черта и ноль) как означающие символ NUL. Некоторые другие реализации делают это только при передаче флага -e.

Так:

echo '\0'

или:

echo -e '\0'

Может привести echoк выводу символа NUL, за которым следует символ LF.

С zsh,

echo $'\0'

передает символ NUL встроенному коду echo.

/bin/echo $'\0'

Не будет работать, потому что /bin/echoэтоказнен, поэтому его аргумент не может содержать символ NUL.

Что касается вашего вопроса по пункту 4. Просто bash игнорирует эти символы NUL. Некоторые другие оболочки ведут себя по-другому.

$ printf 'e\0cho a\0b\n' | bash |& sed -n l
ab$
$ printf 'e\0cho a\0b\n' | ksh |& sed -n l
ksh: syntax error at line 1: `zero byte' unexpected$
$ printf 'e\0cho a\0b\n' | zsh |& sed -n l
zsh: command not found: e$
$ printf 'e\0cho a\0b\n' | rc |& sed -n l
line 1: warning: null character ignored$
line 1: warning: null character ignored$
ab$

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