Representando/citando NUL na linha de comando

Representando/citando NUL na linha de comando

Pode \0ser 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 \0parece 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: \0pode 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 \0como 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 \0na linha de comando para que, por exemplo, você echoveja?

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 zshshell 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, echoimplementaçõ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 -esinalizador é passado.

Então:

echo '\0'

ou:

echo -e '\0'

Pode causar echoa saída do caractere NUL seguido pelo caractere LF.

Com zsh,

echo $'\0'

passa o caractere NUL para o echointegrado.

/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$

informação relacionada