awk比较一个目录下的所有文件&显示出现频率

Awk to compare All the files in a directory & display the frequency of occurrence

假设在一个目录中我有 3 个文件,文件 1、文件 2 和文件 3。具有相同的 header 名称 awk中是否可以比较&写入出现频率

File 1

C1  C2  C3  C4
a   d   a   d
a   d   a   d
a   d   a   d



File 2

C1  C2  C3  C4
a   d   a   d
a   v   a   d
a   d   a   d

File 3 

C1  C2  C3  C4
a   d   r   d
a   f   a   d
a   d   a   d

第 1 步比较文件 1 和文件 2

Temp.output

C1  C2  C3  C4
0   0   0   0
0   1   0   0
0   0   0   0

然后比较文件 2 和文件 3 并用频率

覆盖 Temp.output
Final.Output
C1  C2  C3  C4
0   0   1   0
0   2   0   0
0   0   0   0

原始目录可能包含多个文件,我希望每个文件都按顺序处理,即。 File1.txt 与 file2.txt 然后 file2.txt 与 file3.txt

请在下面找到 awk 脚本。 row = 4 还包括 header

#!/bin/bash
/usr/bin/awk '{print [=10=];}' /tmp/file* | awk -v row=4 -v col=4 '
{
    x = (NR - 1)%row;
    for(i = 1; i <= NF; i++){
        if(a[x, i] != $i){
            a[x, i] = $i;
            count[x, i]++;
        }
    }
}END{
    for(i = 1; i <= row-1; i++){
        for(j = 1; j <= col; j++){
            printf (count[i, j]-1)" ";
        }
        printf "\n";
    }
}'
#

下面的脚本是打印每次迭代

#!/bin/bash

/usr/bin/awk '{print [=11=];}' /tmp/stack/file* | awk -v row=4 -v col=4 '
{
    x = (NR - 1)%row;
    for(i = 1; i <= NF; i++){
        if(a[x, i] != $i){
            a[x, i] = $i;
            count[x, i]++;
        }
    }

    for(i = 1; i <= row-1; i++){
                for(j = 1; j <= col; j++){
                        printf (count[i, j]-1)" ";
                }
                printf "\n";
        }
    print "***********";

}END{
    for(i = 1; i <= row-1; i++){
        for(j = 1; j <= col; j++){
            printf (count[i, j]-1)" ";
        }
        printf "\n";
    }
}'

我建议您将输入文件转换为行。有了这个,您可以轻松申请awk

paste -s <file> 命令是您的盟友。您可以在下面看到如何对文件进行排序并将它们转换为行:

$ cat File1.txt 
C1  C2  C3  C4
a   d   a   d
a   d   a   d
a   d   a   d
$ ls
File1.txt  File2.txt  File3.txt
$ ls | sort
File1.txt
File2.txt
File3.txt
$ ls | sort | xargs -L 1 -I {} /bin/bash -c 'echo -n {}" "; paste -s {}'
File1.txt C1  C2  C3  C4    a   d   a   d   a   d   a   d   a   d   a   d
File2.txt C1  C2  C3  C4    a   d   a   d   a   v   a   d   a   d   a   d
File3.txt C1  C2  C3  C4    a   d   r   d   a   f   a   d   a   d   a   d
$ 

进入行后,您可以使用 awk 迭代字段(NF 会告诉您有多少)。我们将使用几个规则。

对于每一行,您将比较 i 处的字段是否与之前保存的值不同,并相应地增加结果。跳过将第一行的结果与 (NR != 1) 选择器进行比较。

(NR != 1) { for (i = 1; i <= NF; i++) { if (last[i] != $i) { result[i]++; } } }

在同一个 awk 调用中,包括更新保留最后一个值的数组的规则:

{ for (i = 1; i <= NF; i++) { last[i] = $i  }  }

最后打印出文件和结果状态:

{ printf("%s", ); for (i = 1; i <= NF; i++) { printf(" %d", result[i]) } print "" }

这是完整的命令:

$ ls | sort | xargs -L 1 -I {} /bin/bash -c 'echo -n {}" "; paste -s {}' | awk '(NR != 1) { for (i = 1; i <= NF; i++) { if (last[i] != $i) { result[i]++; } } } { for (i = 1; i <= NF; i++) { last[i] = $i  }  } { printf("%s", ); for (i = 1; i <= NF; i++) { printf(" %d", result[i]) } print "" }'
File1.txt 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
File2.txt 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
File3.txt 2 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0
$ 

此输出以文件名开头,然后是累积差异:

  • 文件名(总是不同)
  • 列(C1、C2、C3、C4 始终相同)
  • 然后是你的12个值。您的相关数据从字段 7 开始。

您可以通过 awk 在适当的时候插入新行来重新格式化:

awk '{ print ""; printf("%s", ); for (i = 7; i <= NF; i++) { if (((i - 7) % 4) == 0) print "" ; printf(" %d", $i) } print "" }'

这里有一个完整的运行:

$ ls | sort | xargs -L 1 -I {} /bin/bash -c 'echo -n {}" "; paste -s {}' | awk '(NR != 1) { for (i = 1; i <= NF; i++) { if (last[i] != $i) { result[i]++; } } } { for (i = 1; i <= NF; i++) { last[i] = $i  }  } { printf("%s", ); for (i = 1; i <= NF; i++) { printf(" %d", result[i]) } print "" }' | awk '{ print ""; printf("%s", ); for (i = 7; i <= NF; i++) { if (((i - 7) % 4) == 0) print "" ; printf(" %d", $i) } print "" }'

File1.txt
 0 0 0 0
 0 0 0 0
 0 0 0 0

File2.txt
 0 0 0 0
 0 1 0 0
 0 0 0 0

File3.txt
 0 0 1 0
 0 2 0 0
 0 0 0 0
$