2

Suppose I have two lists of numbers in files f1, f2, each number one per line. I want to see how many numbers in the first list are not in the second and vice versa. Currently I am using grep -f f2 -v f1 and then repeating this using a shell script. This is pretty slow (quadratic time hurts). Is there a nicer way of doing this?

Casebash
  • 114,675
  • 90
  • 247
  • 350
  • Are there dictionaries/hashtables in shell scripting? – Casebash Oct 21 '09 at 11:34
  • What is the format of the file? One number per line? Are the characters supposed to represent integers or floats? Would a python script do? – unutbu Oct 21 '09 at 11:54
  • Here is some information on associative arrays in bash: http://stackoverflow.com/questions/688849/associative-arrays-in-shell-scripts – unutbu Oct 21 '09 at 11:56
  • One number per line. Integers. I don't actually want a Python script because I am trying to learn more shell scripting. (the original purpose of the shell script was to check my python program was working) – Casebash Oct 21 '09 at 12:23

3 Answers3

8

I like 'comm' for this sort of thing. (files need to be sorted.)

$ cat f1
1
2
3
$ cat f2
1
4
5
$ comm f1 f2
        1
2
3
    4
    5
$ comm -12 f1 f2
1
$ comm -23 f1 f2
2
3
$ comm -13 f1 f2
4
5
$ 
2

Couldn't you just put each number in a single line and then diff(1) them? You might need to sort the lists beforehand, though for that to work properly.

Joey
  • 344,408
  • 85
  • 689
  • 683
  • Will that actually provide counts? – Casebash Oct 21 '09 at 12:30
  • Not as such, but you can get that with `grep`/`wc` afterwards. This was just a suggestion on how to improve the quadratic runtime. You will get a somehow (depending on the options to `diff`) readable list of differences. You can just count them, then. – Joey Oct 21 '09 at 12:43
  • Okay, will have to play around with this – Casebash Oct 21 '09 at 13:19
  • diff will have a < for values in the second, but not the first and > for values in the first but not the second. A simple grep and wc should provide the desired answer – Casebash Oct 21 '09 at 23:27
1

In the special case where one file is a subset of the other, the following:

cat f1 f2 | sort | uniq -u

would list the lines only in the larger file. And of course piping to wc -l will show the count.

However, that isn't exactly what you described.

This one-liner serves my particular needs often, but I'd love to see a more general solution.

pavium
  • 14,808
  • 4
  • 33
  • 50