比较不同文件之间的列

比较不同文件之间的列

我有多个文件(大约 20 个文件,包含 30000 行和 32 列),并且我只需要保留以相同字符串开头的行。我发现这些案例与我需要的非常相似,但我不知道如何适应它们。

将多个文件(两个以上)与两个不同的列进行比较

如何比较两个不同文件中两列中的值,回显完整行,其中差异的绝对值<一个小的最大值?

在我的例子中,每个文件的第一列由 12 个字符的字符串组成,我只需要保留以所有文件中存在的字符串开头的行。 (每个输入文件一个文件,或者像上述情况下的一个输出文件也可以)。我的文件是这样的:

文件1:

 -13  -5   0 19.3769 46.9197   1
 -13  -4  -2 347.911 57.7232   1
 -13  -4  -1 38.5696 39.0027   1
 -13  -4   0 2227.39 124.894   1
 -13  -3  -3 113.001 40.2117   1
 -13  -3  -2 850.847 78.2881   1

文件2:

 -13  -5   0 2.19085 50.4632   1
 -13  -4  -2 283.628 56.7731   1
 -13  -4  -1  41.179 48.6423   1
 -13  -4   0 1753.54  125.88   1
 -13  -3  -3 28.2363 40.6518   1
 -13  -3  -2 562.736 66.0301   1
 -13  -3  -1 750.747 77.2795   1

输出文件1:

 -13  -5   0 19.3769 46.9197   1
 -13  -4  -2 347.911 57.7232   1
 -13  -4  -1 38.5696 39.0027   1
 -13  -3  -3 113.001 40.2117   1
 -13  -3  -2 850.847 78.2881   1

输出文件2

 -13  -5   0 2.19085 50.4632   1
 -13  -4  -2 283.628 56.7731   1
 -13  -4  -1  41.179 48.6423   1
 -13  -3  -3 28.2363 40.6518   1
 -13  -3  -2 562.736 66.0301   1

答案1

一种方法是首先查找多个文件中存在的所有 12 个初始字符集:

cut -c-12 file* | sort | uniq -c

上面的命令cut打印每个名称以 开头的文件的前 12 个字符file,然后对这些字符进行排序,并在每行的找到次数后附加uniq -c。在示例文件上运行此命令将返回:

$ cut -c-12 file* | sort | uniq -c
      1  -13  -3  -1
      2  -13  -3  -2
      2  -13  -3  -3
      2  -13  -4   0
      2  -13  -4  -1
      2  -13  -4  -2
      2  -13  -5   0

因此,除了第一行之外的所有行都出现在两个文件中。现在,仅保留那些出现所需次数的行(在您的情况下为 20 次):

cut -c-12 file* | sort | uniq -c | rev | sed -n 's/ 20 *$//p' | rev

rev只是将其输入反转打印。我在这里使用它来计算每行最后一个字段被看到的次数。然后将其传递给sed它,告诉它仅打印以空格、20 和 0 或更多空格结尾的行。这仅保留出现了 20 次的台词,最后rev将我们带回原始格式。

您现在可以将整个内容grep作为字符串列表传递以进行搜索:

$ grep -f <(cut -c-12 file* | sort | uniq -c | 
            rev | sed -n 's/ 20 *$//p' | rev) file*
 -13  -5   0 19.3769 46.9197   1
 -13  -4  -2 347.911 57.7232   1
 -13  -4  -1 38.5696 39.0027   1
 -13  -4   0 2227.39 124.894   1
 -13  -3  -3 113.001 40.2117   1
 -13  -3  -2 850.847 78.2881   1

如果您的 shell 不支持该<()格式,您可以将结果保存cut在单独的文件中并使用它,或者只是在循环中运行它:

cut -c-12 file* | sort | uniq -d | 
    while IFS= read -r l; do grep -- "^$l" file1; done

要将每个文件的输出放在单独的文件中,请使用:

cut -c-12 file* | sort | uniq -c | rev | sed -n 's/ 20 *$//p' | rev > list
for f in file*; do grep -f list "$f" > "$f.new"; done

相关内容