让我建议您将输入文件转换为行。有了这个,你就可以轻松申请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", $1); 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", $1); 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", $1); 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", $1); for (i = 1; i <= NF; i++) { printf(" %d", result[i]) } print "" }' | awk '{ print ""; printf("%s", $1); 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
$