bashzshheredocprocess-substitution

Process substitution with heredoc works in zsh. How to make it work in bash?


I want the ability to pass a heredoc to the source command for local interpretation. The body of the heredoc document will be injected later before calling the script, and can be multiline.

I came up with this trick, which works in zsh:

source <(<<'heredoc'
echo foo
sleep 10
echo done
heredoc
) && echo ok || echo no

it prints foo, sleeps 10 seconds, then prints done, then ok. So far, so good.

Now, the script needs to run in bash. When I feed bash (or sh) the exact same thing, I only get ok, with no wait at all, as if the command I was providing with the heredoc was just true.

I cannot understand why, and how I can build the same behavior in bash and sh.


Solution

  • How to make it work in bash?

    Remove any here documents and execute the commands. You could preserve the group.

    {
       echo foo
       sleep 10
       echo done
    } && echo ok || echo no
    

    You can use, both in zsh and bash, source /dev/stdin if you want to execute commands in the current execution environment coming from a steam, like a here document. No need for <( process substitution in either case. So here you go:

    source /dev/stdin <<heredoc
    echo foo
    sleep 10
    echo done
    heredoc
    

    Note: this looks very odd thing to do and most probably there are better solutions to what you are doing.

    why

    Because in bash empty redirection like a here document without a command does nothing. You have to for example cat the content of the stream created by here document to output it to standard output for process substation to capture it.