Unix 显示文件2中存在但不在文件1中的记录

Unix 显示文件2中存在但不在文件1中的记录,unix,programming-languages,file-io,Unix,Programming Languages,File Io,日志文件1包含昨天访问过的客户的记录(姓名、id、日期) 日志文件2包含今天访问的客户的记录(姓名、id、日期) 您将如何显示昨天访问但今天未访问的客户 约束条件是:不要使用辅助数据结构,因为文件包含数百万条记录。[因此,没有散列] 有没有办法使用Unix命令执行此操作???是否通过id标识客户?它是int还是long?如果这两个问题的答案都是肯定的,那么一个包含10000000个整数的数组不应该占用超过10M*4=40MB的内存——这对普通硬件来说不是什么大问题。简单地对它们进行排序和比较 顺

日志文件1包含昨天访问过的客户的记录(姓名、id、日期) 日志文件2包含今天访问的客户的记录(姓名、id、日期)

您将如何显示昨天访问但今天未访问的客户

约束条件是:不要使用辅助数据结构,因为文件包含数百万条记录。[因此,没有散列]
有没有办法使用Unix命令执行此操作???

是否通过id标识客户?它是int还是long?如果这两个问题的答案都是肯定的,那么一个包含10000000个整数的数组不应该占用超过10M*4=40MB的内存——这对普通硬件来说不是什么大问题。简单地对它们进行排序和比较

顺便说一句,在我的机器上对一个包含10M个随机整数的数组进行排序只需不到2秒的时间——同样,没什么好害怕的

下面是一些非常简单的Java代码:

public static void main(final String args[]) throws Exception {

    // elements in each log file
    int count = 10000000;

    // "read" our log file
    Random r = new Random();
    int[] a1 = new int[count];
    int[] a2 = new int[count];
    for (int i = 0; i < count; i++) {
        a1[i] = Math.abs(r.nextInt());
        a2[i] = Math.abs(r.nextInt());
    }

    // start timer
    long start = System.currentTimeMillis();

    // sort logs
    Arrays.sort(a1);
    Arrays.sort(a2);

    // counters for each array
    int i1 = 0, i2 = 0, i3 = 0;

    // initial values
    int n1 = a1[0], n2 = a2[0];

    // result array
    int[] a3 = new int[count];

    try {
        while (true) {
            if (n1 == n2) {
                // we found a match, save value if unique and increment counters
                if (i3 == 0 || a3[i3-1] != n1) a3[i3++] = n1;
                n1 = a1[i1++];
                n2 = a2[i2++];
            } else if (n1 < n2) {
                // n1 is lower, increment counter (next value is higher)
                n1 = a1[i1++];
            } else {
                // n2 is lower, increment counter (next value is higher)
                n2 = a2[i2++];
            }
        }
    } catch (ArrayIndexOutOfBoundsException e) {
        // don't try this at home - it's not the pretties way to leave the loop!
    }

    // we found our results
    System.out.println(i3 + " commont clients");
    System.out.println((System.currentTimeMillis() - start) + "ms");

}

正如您所看到的,在每个日志中创建10万条记录非常有效,我个人打算创建一个数据结构和访问记录,但是,我也可以看到您是如何用另一种方式来完成的

在伪代码中,这看起来像python,但可以用perl或shell脚本或

import subprocess 
import os

for line in fileinput.input(['myfile'])::
    # split out data. For the sake of it I'm assuming name\tid\tdate
    fields = line.split("\")
    id = fields[1]

    grepresult = subprocess.Popen("grep \"" + id + "\" file1", shell=True, bufsize=bufsize, stdout=PIPE).stdout

    if len(grepresult) == 0:
        print fields # it wasn't in field1
这并不完美,没有经过测试,所以请适当处理,但它为您提供了如何使用unix命令的要点。也就是说,正如Sfussenger指出的那样,如果您使用的是C/C++,那么它应该能够处理相当大的文件


免责声明:这是一个不太符合问题要求的解决方案(反复调用grep)。如果我正在这样做,我会使用C.

作为示例,但请查看
comm
的手册页以获取所需的选项

comm -2 <(sort -u yesterday) <(sort -u today)

通过使用unix工具
uniq
,有。不过,我非常确定它不会使用任何额外的数据结构(我敢打赌它会使用)。文件分类了吗?在我看来,你需要为此提出定制的解决方案。这种合并(排序)很适合,但您需要对文件进行排序…unix comm工具可用于比较一对排序的文件,并显示每个文件的公用行和/或唯一行。您必须对记录进行排序并可能进行重复数据消除(sort-u,uniq),这意味着要编写新文件。+1,我打赌这比我刚才编写的脚本快得多,而且绝对是正确的方法。
comm -2 <(sort -u yesterday) <(sort -u today)
diff <(sort -u yesterday) <(sort -u today)