Redirect / pipe into read command

2019-08-30 19:30发布

问题:

This is a follow-up to my previous question on SO. I am still trying to command a script deepScript from within another script shallowScript and process its output before display on terminal. Here is a code sample:

deepScript.sh

#!/bin/zsh
print "Hello - this is deepScript"
read "ans?Reading : "
print $ans

shallowScript.sh

#!/bin/zsh

function __process {
    while read input; do
        echo $input | sed "s/e/E/g"
    done }

print "Hello - this is shallowScript"
. ./deepScript.sh |& __process

(edited : outcome of this syntax and of 2 alternatives pasted below)

[UPDATE]

I have tried alternative syntaxes for last redirection . ./deepScript.sh |& __process and each syntax has a different outcome, but of course none of them is the one I want. I'll just paste each syntax and the resulting output of ./shallowScript.sh (where I typed "input" when read was waiting for an input), together with my findings so far.

Option 1 : . ./deepScript.sh |& __process

From this link, it seems that . ./deepScript.sh is run from a subshell, but not __process. Output:

zsh : ./shallowScript.sh
Hello - this is shallowScript
HEllo - this is dEEpScript
input
REading : input

Basically, the first two lines are printed as expected, then instead of printing the prompt REading :, the script directly waits for the stdin input, and then prints the prompt and executes print $ans.

Option 2: __process < <(. ./deepScript.sh)

Zsh's manpage indicates that (. ./deepScript.sh) will run as a subprocess. To me, that looks similar to Option 1. Output:

Hello - this is shallowScript
Reading : HEllo - this is dEEpScript
input
input

So, within . ./deepScript.sh, it prints read's prompt (script line 3) before the print (script line 2). Strange.

Option 3: __process < =(. ./deepScript.sh)

According to the same manpage, (. ./deepScript.sh) here sends its output to a temp file, which is then injected in __process (I don't know if there is a subprocess or not). Output:

Hello - this is shallowScript
Reading : input
HEllo - this is dEEpScript
input

Again, deepScript's line 3 prints to the terminal before line 2, but now it waits for the read to be complete.

Two questions:

  • Should this be expected?
  • Is there a fix or a workaround?

回答1:

The observed delay stems from two factors:

  1. deepScript.sh and process run asynchronously
  2. read reads a complete line before returning

deepScript.sh writes the prompt to standard error, but without a newline. It then waits for your input while process continues to wait for a full line to be written so that its call to read can finish.