Enquanto eu estava lendo esta resposta , o autor usou este comando para colocar o resultado de um heredoc em uma variável:
read -r -d '' VAR <<'EOF'
abc'asdf"
$(dont-execute-this)
foo"bar"''
EOF
Estou um pouco confuso sobre a -d
opção. Do texto de ajuda para o read
comando:
-d delim
continue until the first character of DELIM is read, rather than newline
Então, se eu passar uma string vazia para -d
, significa ler até a primeira string vazia . O que isto significa? O autor comentou na resposta que -d ''
significa usar a string NUL como delimitador. Isso é verdade (string vazia significa string NUL)? Por que não usar algo como -d '\0'
ou -d '\x0'
etc.?
Principalmente, significa o que diz, por exemplo:
A leitura termina imediatamente no
.
, não apertei enter lá.Mas
read -d ''
é um caso um pouco especial, o manual de referência on-line diz :\0
significa o byte NUL emprintf
, então temos, por exemplo:No seu exemplo,
read -d ''
é usado para evitar que a nova linha seja o delimitador, permitindo que ele leia a string de várias linhas de uma só vez, em vez de uma linha de cada vez.Acho que algumas versões mais antigas da documentação não mencionaram explicitamente
-d ''
. O comportamento pode originalmente ser uma coincidência não intencional de como o Bash armazena strings no modo C, com esse byte NUL à direita. A stringfoo
é armazenada comofoo\0
, e a string vazia é armazenada apenas como\0
. Portanto, se a implementação não for cuidadosa em se proteger e escolher apenas o primeiro byte na memória, verá\0
, NUL, como o primeiro byte de uma string vazia.Relendo a pergunta mais de perto, você mencionou:
Isso não é exatamente certo. A string nula (no jargão POSIX) significa a string vazia, uma string que não contém nada, de comprimento zero. Isso não é o mesmo que o byte NUL , que é um único byte com valor binário zero (*) . Se você usasse a string vazia como delimitador, a encontraria praticamente em todos os lugares, em todas as posições possíveis. Eu não acho que isso seja possível no shell, mas, por exemplo, em Perl, é possível dividir uma string assim, por exemplo:
read -d ''
usa o byte NUL como separador.(*não é o mesmo que o personagem
0
, é claro.)Bem, essa é uma boa pergunta. Como Stéphane comentou, originalmente, o ksh93
read -d
não suportavaread -d ''
isso, e alterá-lo para suportar escapes de barra invertida seria incompatível com o original. Mas você ainda pode usarread -d $'\0'
(e da mesma forma$'\t'
para a guia, etc.) se preferir. Apenas isso nos bastidores, é o mesmo que-d ''
, já que o Bash não suporta o byte NUL em strings. Zsh faz, mas parece aceitar ambos-d ''
e-d $'\0'
.Apenas para apontar a perspicácia do ascii 0 como um caractere em arquivos. Expect (minha ferramenta favorita!) tem que fazer provisões especiais para leitura/correspondência de nulos.