## 11.9. More Friendly comm Output

Section 11.8 didn't show one of my least-favorite comm features. The default output (with text in "columns") confuses me if the lines of output have much text (especially text with spaces). For example, if I'm looking at two who (Section 2.8) listings to compare who was logged on at particular times, the columns in the who output are jumbled:

>     $ comm who1 who2
>                     root     tty1     Oct 31 03:13
>                     jpeek    tty2     Oct 31 03:15
>     jpeek    pts/0    Oct 31 03:19
>                     jpeek    pts/1    Oct 31 03:19
>                     jpeek    pts/2    Oct 31 03:19
>     ally     pts/4    Oct 31 03:19
>                     jpeek    pts/3    Oct 31 03:19
>             xena     pts/5    Nov  3 08:41

The commer script (see later) filters the comm output through sed. It converts comm's indentation characters (one TAB for lines in "column 2" and two TABs for lines in "column 3") into labels at the start of each output line. The default output looks like this:

>     $ commer who1 who2
>     BOTH>root     tty1     Oct 31 03:13
>     BOTH>jpeek    tty2     Oct 31 03:15
>      TWO>jpeek    pts/0    Oct 31 03:19
>     BOTH>jpeek    pts/1    Oct 31 03:19
>     BOTH>jpeek    pts/2    Oct 31 03:19
>      TWO>ally     pts/4    Oct 31 03:19
>     BOTH>jpeek    pts/3    Oct 31 03:19
>      ONE>xena     pts/5    Nov  3 08:41

With the -i option, the script uses both labels and columns:

>     $ commer -i who1 who2
>     BOTH>           root     tty1     Oct 31 03:13
>     BOTH>           jpeek    tty2     Oct 31 03:15
>      TWO>jpeek    pts/0    Oct 31 03:19
>     BOTH>           jpeek    pts/1    Oct 31 03:19
>     BOTH>           jpeek    pts/2    Oct 31 03:19
>      TWO>ally     pts/4    Oct 31 03:19
>     BOTH>           jpeek    pts/3    Oct 31 03:19
>      ONE>   xena     pts/5    Nov  3 08:41

Go to http://examples.oreilly.com/upt3 for more information on: commer

Here's the script. The sed substitute (`s`) commands have one or two TABs between the first pair of slashes. Note that the sed script is inside double quotes (`"`), so the shell can substitute the value of `$indent` with an ampersand (`&`) into the sed script if the -i option was used:

>     #!/bin/sh
>     # commer - label columns in "comm" output
>     # Usage: commer [-i] file1 file2
>     #   -i option indents output lines into columns as "comm" does
>     #
>     # Note that script WILL FAIL if any input lines start with a TAB.

>     case "$1" in
>     -i) indent='&'; shift ;;
>     -*|"") echo "Usage: `basename $0` [-i] file1 file2" 1>&2; exit 1 ;;
>     esac

>     # In "comm" output, column 1 (lines in file 1) has no leading TAB.
>     # Column 2 (lines in file 2) has one leading TAB.
>     # Column 3 (lines in both files) has two leading TABs.
>     # Search for these tabs and use them to label lines.
>     # (You could replace ONE and TWO with the filenames $1 and $2)
>     comm "$1" "$2" |
>     sed "{
>     /^              / {s//BOTH>$indent/; b}
>     /^      / {s// ONE>$indent/; b}
>     s/^/ TWO>/
>     }"

> NOTE: The commer script will be fooled by lines that already have TAB characters at the start. If this might be a problem, you can modify the script to search the files (`grep "^TAB" >/dev/null`) before starting comm.

-- JP

Copyright © 2003 O'Reilly & Associates. All rights reserved.