Existem duas deficiências no bash que compensam umas às outras.
Quando você escreve $'-d
'
, isso é tratado internamente de forma idêntica à string vazia. Por exemplo:
$ a=$'# a=$'foo$ a=$'# a=$'foo%pre%bar'; echo "$a"; echo ${#a}
foo
3
'; echo ${#a}
0
bar'; echo "$a"; echo ${#a}
foo
3
'; echo ${#a}
0
Isso ocorre porque o bash internamente armazena todas as strings como strings C , que são terminada em null - um byte nulo marca o final da string. Bash silenciosamente trunca a string para o primeiro byte nulo (que não faz parte da string!).
%pre%
Quando você passa uma string como um argumento para a opção read
do read
builtin, o bash só olha para o primeiro byte da string. Mas na verdade não verifica se a string não está vazia. Internamente, uma string vazia é representada como uma matriz de bytes de 1 elemento que contém apenas um byte nulo. Então, ao invés de ler o primeiro byte da string, o bash lê este byte nulo.
Então, internamente, o maquinário por trás do ksh -d ""
construído funciona bem com bytes nulos; ele continua lendo byte por byte até encontrar o delimitador.
Outras conchas se comportam de maneira diferente. Por exemplo, ash e ksh ignoram os bytes nulos quando lêem a entrada. Com ksh, $'read -d ''
'
lê até uma nova linha. Os shells são projetados para lidar bem com texto, não com dados binários. Zsh é uma exceção: ele usa uma representação de string que lida com bytes arbitrários, incluindo bytes nulos; em zsh, read -d $'%code%'
é uma cadeia de comprimento 1 (mas %code% , estranhamente, se comporta como %code% ).