Seu problema não é com o shell, ou com o doc aqui, mas com Expect, pegando a $def
como referência de variável e tentando expandi-la.
Aqui, bar
é uma variável definida no Expect e expandida lá (isso é simples, o shell não expande $bar
):
$ expect -f - <<< 'set bar abcdefg; send_user "foo$bar\n"'
fooabcdefg
Isto dá o mesmo erro que você viu (o script expect é citado duas vezes agora, então $var
faz expandir no shell, ao contrário do anterior):
$ var='foo$bar'; expect -f - <<< "send_user \"$var\n\""
can't read "bar": no such variable
while executing
"send_user 'foo$bar\n'"
Você precisaria escapar do $
, mas também precisaria escapar pelo menos de [
, pois também é especial em Expectar, ou melhor, no Tcl, no qual o Expect se baseia. Talvez haja outros também, não tenho certeza ...
Pode ser mais fácil transmitir o valor por meio de um argumento de linha de comando:
$ var='foo$bar[quux]'
$ expect -f - "$var" <<< 'set var [lindex $argv 0]; send_user "$var\n"'
foo$bar[quux]
Ou através do ambiente:
$ export var
$ expect -f - "$var" <<< 'set var $::env(var); send_user "$var\n"'
foo$bar[quux]
Um pouco mais perto do que seu código faz:
#!/bin/bash
line='2.3.4.5:abc$def'
IFS=: read host pw <<< "$line"
export host pw
expect -f - << 'EOF'
set host $::env(host)
set pw $::env(pw)
send_user "host is '$host' pw is '$pw'\n"
EOF
Com as variáveis passadas pelo ambiente, você pode fazer o aqui-doc citado de modo que o shell não expanda o $
s e use as variáveis esperadas $host
e $pw
quando necessário.