I know a redirection is all I need, just never got to remember how exactly to do that even it’s dead simple. Therefore, this post is written and I hope will never need to read this post, because that means I would’ve remembered how to do it.
Contents
1 The loop which doesn’t work
From time to time, there is a script that needs read both user input and lines from a file, it all begins with:
while read line; do echo "LINE : $line" read -p "INPUT> " echo "REPLY: $REPLY" done <FILE
Note
read reads into $REPLY by default, if you don’t supply a variable name.
With an input FILE that is three lines of numbers:
for i in {01..03}; do echo $i; done >FILE
That will never work as you wanted, because both reads read from the same file, since within that loop, the standard input, &0, is no longer from your keyboard, but the <FILE. You will get this output:
LINE : 01 REPLY: 02 LINE : 03 REPLY:
You can see the read within loop also reads from the FILE. You will expect to have an output and inputs like:
LINE : 01 INPUT> a REPLY: a LINE : 02 INPUT> b REPLY: b LINE : 03 INPUT> c REPLY: c
2 Redirecting FILE
while read -u 3 line; do echo "LINE : $line" read -p "INPUT> " echo "REPLY: $REPLY" done 3<FILE
The file read reads from file descriptor 3 which is a redirection from the FILE using 3<FILE. Since &0 is untouched, the read in the loop can still read from keyboard without problems.
3 Opening FILE as file descriptor
You can also open the FILE as &3, this can be used throughout the script, if somehow cross loop reading is needed:
exec 3<FILE while read -u 3 line; do echo "LINE : $line" read -p "INPUT> " echo "REPLY: $REPLY" done exec 3<&-
The last exec closes the file.
4 Duplicating the stdin
exec 3<&0 while read line; do echo "LINE : $line" read -p "INPUT> " -u 3 echo "REPLY: $REPLY" done <FILE exec 3<&-
The file read reads like any other file reading loop, but the read inside, it reads from &3, which is a duplicate of standard input from outside of loop, that is the keyboard input we want.
This means, when in outside of the loop, after exec, both &0 and &3 are from keyboard, but as entering the loop, the &0 will be from the file because of <FILE. However, once the loop ends, the &0 will be restored and you can safely read from keyboard through it again.
The last line closes &3 to end the duplication of &0.
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.