Sams Teach Yourself Shell Programming in 24 Hours
(Publisher: Macmillan Computer Publishing)
Author(s): Sriranga Veeraraghavan
ISBN: 0672314819
Publication Date: 01/01/99

Previous Table of Contents Next


Using Multiple sed Commands

As you can see from the last example, you were able to update the prices, but Paech is still misspelled. Say that you need to update fruit_prices.txt with both changes. This means that you have to perform more than one sed command on the file. You can do this in two ways:

  Perform the first change and then update the file. Perform the second change command and then update the file.
  Perform both changes using a single sed command and then update the file once.

As you can guess, the second method is much more efficient and less prone to error because the file is updated only once. You can perform both changes using a single sed command as follows:

sed -e 'command1' -e 'command2' ... -e 'commandN' files

Here command1 through commandN are sed commands of the type discussed previously. These commands are applied to each of the lines in the list of files given by files.

In this case you can perform both updates using either of the following commands:

$ sed -e 's/Paech/Peach/' -e 's/ *[0-9][0-9]*\.[0-9][0-9]$/\$&/'
⇒fruit_prices.txt
Fruit           Price/lbs
Banana          $0.89
Peach           $0.79
Kiwi            $1.50
Pineapple       $1.29
Apple           $0.99

To update the file you use the same procedure as before:

$ mv fruit_pieces.txt fruit_pieces.txt.$$
$ sed -e 's/Paech/Peach/' -e 's/ *[0-9][0-9]*\.[0-9][0-9]$/\$&/'
⇒fruit_prices.txt.$$ > fruit_pieces.txt
$ cat fruit_pieces.txt
Fruit           Price/lbs
Banana          $0.89
Peach           $0.79
Kiwi            $1.50
Pineapple       $1.29
Apple           $0.99

Using sed in a Pipeline

As I have mentioned before, if sed does not receive a list of files, it acts on its STDIN. This enables us to use it in pipelines.

I will demonstrate sed’s usage in this manner by using it to solve the problem of determining the user’s numeric user ID (uid).

On all UNIX systems the /usr/bin/id command prints the current users uid and gid information. In my case, the output of id looks like the following:

$ /usr/bin/id
uid=500(ranga) gid=100(users)

As you can tell from the output, my numeric uid is 500. You need to modify this output so that only this number is printed. Using sed makes this task quite easy.

First you need to eliminate everything following the first parenthesis. You can do that as follows:

$ /usr/bin/id | sed 's/(.*$//'

Now the output looks like the following:

uid=500

If you eliminate the uid= portion at the beginning of the line, you are finished. You can do this as follows:

$ /usr/bin/id | sed -e 's/(.*$//' -e 's/^uid=//'

Now the output is

500

This is what you want. Notice that when you added the second s command, you changed from the single command form for sed to the multiple command form that uses the -e option.

Summary

In this chapter you looked at filtering text using regular expressions. Some of the major topics that you covered are

  Matching characters
  Specifying sets of characters
  Anchoring patterns
  Escaping metacharacters

You also covered the similarities between the two most powerful text filtering programs available on UNIX systems, awk and sed. Finally, you looked at using the sed command. Some of the uses that you covered are

  Printing lines
  Deleting lines
  Performing substitution

In the next chapter I will introduce the awk command and its programming language. Using the material covered in this chapter, you will be able to use awk to easily perform difficult text manipulations.

Questions

1.  Using sed, write a shell function that searches for a word or simple expression in a list of files, printing out a list of matches. This is similar to the grep program.
You do not have to support all possible sed expressions. Your function should take the word to look for as its first argument. It should treat its other arguments as a list of files.
HINT: Use double quotes (") instead of single quotes (') to surround your sed script.
2.  Write a sed command that takes as its input the output of the uptime command and prints only the last three load averages. The uptime command’s output looks like the following:
$ uptime
6:34pm  up 2 day(s), 49 min(s),  1 user,  load average:
0.00, 0.00, 0.02

Your output should look like the following:
load average: 0.05, 0.01, 0.03
3.  Write a sed command that takes as its input the output of the command df -k and prints only those lines that start with a /. The output of the df -k command looks like the following:
Filesystem          kbytes   used  avail capacity  Mounted on
/dev/dsk/c0t3d0s0   739262 455143 224979    67%    /
/proc                    0      0      0     0%    /proc
fd                       0      0      0     0%    /dev/fd
/dev/dsk/c0t3d0s1   123455   4813 106297     5%    /var
/dev/dsk/c0t3d0s5   842150 133819 649381    18%    /opt
swap                366052  15708 350344     5%    /tmp
kanchi:/home       1190014 660165 468363    59%    /users

On HP-UX use the command df -b instead of df -k.
4.  Write a sed command that takes as its input the output of the ls -l command and prints the permissions and the filename for regular files. Directories, links, and special files should not appear in the output. The output of ls -l should look similar to the following:
-rw-r--r--  1 ranga users  85 Nov 27 15:34 fruit_prices.txt
-rw-r--r--  1 ranga users  80 Nov 27 13:53 fruit_prices.txt.7880
lrwxrwxrwx  1 ranga users   8 Nov 27 19:01 nash -> nash.txt
-rw-r--r--  1 ranga users  62 Nov 27 16:06 nash.txt
lrwxrwxrwx  1 ranga users   8 Nov 27 19:01 urls -> urls.txt
-rw-r--r--  1 ranga users 180 Nov 27 12:34 urls.txt

Your output should look like:
-rw-r--r-- fruit_prices.txt
-rw-r--r-- fruit_prices.txt.7880
-rw-r--r-- nash.txt
-rw-r--r-- urls.txt


Previous Table of Contents Next