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
$
假设在一个目录中我有 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.outputFinal.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
$