read
is a very useful tool; it might seem too simple to bother mentioning, but there are at least three different ways to use it. (Okay, two, and the third isn’t really anything special about read
, just a nifty thing that the shell itself provides)…
1. Read the whole line
Let’s start with an interactive script:
$ cat readme.sh #!/bin/sh echo "I'm a parrot!" while read a do echo "A is $a" done $ ./readme.sh I'm a parrot! hello A is hello one two three A is one two three piglet eeyore pooh owl A is piglet eeyore pooh owl ^D $
Yes, you’ll need to hit CTRL-D to exit this loop, it’s just a simple example.
So far, so stupid. But wait; what if I wanted to get that “one” “two” “three” and use them differently?
2. Read the words
$ cat readme.sh #!/bin/sh echo "I'm a parrot!" while read a b c do echo "A is $a" echo "B is $b" echo "C is $c" done $ ./readme.sh I'm a parrot! hello A is hello B is C is one two three A is one B is two C is three piglet eeyore pooh owl A is piglet B is eeyore C is pooh owl ^D $
So, just by naming some variables, we can pick what we get. And – did you see that last one? We don’t lose anything, either… Just because we asked for three variables (a, b, c) and we got 4 values (piglet eeyore pooh owl), we didn’t lose anything; the last one was treated like a normal read.
This is actually pretty handy stuff; you’d have to do a bit of messing about with pointers to get the same effect in C, for example.
3. Read from a file
We can do all this from a file, too. This isn’t special to read
, but it’s often used in this way. See that “while – do – done” loop? It’s a sub-shell, and we can direct whatever we want to its input (everything is a file, remember, so the keyboard, a text file, a device driver, whatever you want, it’s all just a file)
We do this with the “<
” operator. Just add “< filename.txt
” after the “done
” end of the loop:
$ cat readme.sh #!/bin/sh echo "I'm a parrot!" while read a b c do echo "A is $a" echo "B is $b" echo "C is $c" done < myfile.txt $ cat myfile.txt 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 $ ./readme.sh I'm a parrot! A is 1 B is 2 C is 3 A is 4 B is C is A is 5 B is 6 C is A is 7 B is C is A is 8 B is 9 C is 10 11 12 13 A is 14 B is C is A is 15 B is 16 C is 17
So we can process tons of data, wherever it comes from.
4. I only mentioned 3 uses
We could make the script a bit more useful, by allowing the user to specify the file, instead of hard-coding it to “myfile.txt
“:
$ cat readme.sh #!/bin/sh echo "I'm a parrot!" while read a b c do echo "A is $a" echo "B is $b" echo "C is $c" done < $1 $ cat someotherfile.txt 123 1 2 3 one two three four $ ./readme.sh someotherfile.txt I'm a parrot! A is 123 B is C is A is 1 B is 2 C is 3 A is one B is two C is three four $
Update 14 April
Updated to fix the “done < filename.txt” from the example code of the last two examples.