Existem vários problemas com sua pergunta.
A linha
4>&1 1>&3
Está faltando um exec:
exec 4>&1 1>&3
E a linha:
exec 1>4&-
Deve ler
exec 1>&4-
Um script simplificado deve ficar assim:
GetString()
{
exec 4>&1 1>&3 #save pipe end and change output back to caller's
printf "some stuff for the interactive user\n"
sleep 3
exec >&4- #change output back to pipe end
echo "test value"
}
exec 3>&1
string=$(GetString)
echo "final value <$string>"
Este script faz sentido.
Edite a pergunta para realmente reproduzir seu problema.