Pode \0
ser usado na linha de comando?
Fundo
Para testar casos extremos no GNU Parallel, fiquei curioso para saber se todos os caracteres foram citados corretamente na linha de comando. Muitos deles são:
perl -e 'print pack ("c*",1..255,10)' | parallel -k echo | md5sum
d03484ca75b3e38be411198d66bf4611 -
perl -e 'print pack ("c*",1..255,10)' | md5sum
d03484ca75b3e38be411198d66bf4611 -
Mas \0
parece ser complicado (aqui ilustrado com 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)
Posso justificar o segundo exemplo: \0
pode ser interpretado como EOS, mas esse também deveria ser o caso no exemplo 4. O exemplo 3 enfatiza que o GNU Parallel não é visto \0
como EOS, mas o passa para bash
.
Você pode explicar o que está acontecendo? Especialmente o caso 4 me intriga.
E mais importante:
Existe uma maneira de citar \0
na linha de comando para que, por exemplo, você echo
veja?
Responder1
Ao executar um comando, a lista de argumentos é uma lista de ponteiros para strings terminadas em NUL passadas para a execve()
chamada do sistema (assim como as variáveis de ambiente que são a outra lista de strings terminadas em NUL passadas para execve()
).
Como resultado, argumentos e variáveis de ambiente deexecutadocomandos não podem conter o caractere NUL.
A exceção a isso são os internos e as funções no zsh
shell cujos argumentos podem conter qualquer coisa (esses são integrados, portanto a execve()
chamada do sistema não está envolvida).
Você pode passar dados com caracteres NUL via stdin (ou qualquer outro descritor de arquivo) ou em qualquer tipo de arquivo. Ou algum comando entende alguma forma de codificação.
Por exemplo, echo
implementações em conformidade com UNIX entendem \0
(os dois caracteres barra invertida e zero) como significando o caractere NUL. Algumas outras implementações fazem isso somente quando o -e
sinalizador é passado.
Então:
echo '\0'
ou:
echo -e '\0'
Pode causar echo
a saída do caractere NUL seguido pelo caractere LF.
Com zsh
,
echo $'\0'
passa o caractere NUL para o echo
integrado.
/bin/echo $'\0'
Não funcionaria porque /bin/echo
éexecutado, portanto, seu argumento não pode conter o caractere NUL.
Quanto à sua pergunta do ponto 4. É que o bash ignora esses caracteres NUL. Alguns outros shells se comportam de maneira diferente.
$ 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$