piping output of process to sh while loop?

2019-08-08 20:45发布

I'm trying to loop over the output of a Perl process, line by line, within a while loop. However, I'm having difficulty with the syntax.

I tried this, but got an "ambiguous redirect" error:

#!/bin/sh

while read line; do 
    echo "$line" 
    # do stuff with $line 
done < $(perl process.pl)

./script.sh : line 6: $(perl process.pl): ambiguous redirect

For instance, one (inefficient) solution would be:

#!/bin/sh

tmpFile=/tmp/tmpFile.txt
perl process.pl > $tmpFile 
while read line; do 
    echo "$line" 
    # do stuff with $line 
done < $tmpFile

I know I can pipe the Perl process to a while loop as:

perl process.pl | while ...

but the while loop is executed in a subshell, and I need some variables set in the while loop to remain after the loop finished, so this is not an option.

What can I do?

标签: while-loop sh
3条回答
冷血范
2楼-- · 2019-08-08 21:31

Use a here-document:

while IFS= read -r line; do
    echo "$line" 
    # do stuff with $line 
done <<EOF
$(perl process.pl)
EOF
查看更多
爱情/是我丢掉的垃圾
3楼-- · 2019-08-08 21:33

You're almost there. Try this:

while read -r line; do 
    echo "$line" 
    # do stuff with $line 
done < <(perl process.pl)

The only difference is the < instead of the $.

$(cmd) is a command substitution, which expands to the output of the command within the parentheses. On the other hand, <(cmd) is a process substitution. Note that this is a Bash extension, so you should also change your shebang to be #!/bin/bash if you want to use this method.

Alternatively, if you are not using Bash, you can simply use a pipe instead:

perl process.pl | while read -r line; do 
    echo "$line" 
    # do stuff with $line 
done

As an aside, you almost always want to use the -r switch with read

查看更多
我只想做你的唯一
4楼-- · 2019-08-08 21:35

Use a named pipe; bash process substitution is essentially syntactic sugar around this.

mkfifo output
perl process.pl > output &
while IFS= read -r line; do 
    echo "$line" 
    # do stuff with $line 
done < output
rm output

The named pipe does not require process.pl to complete before the while loop begins consuming the output.

查看更多
登录 后发表回答