Awk 计算文件中的错误数

Awk 计算文件中的错误数,awk,Awk,我有一个名为result.txt的文件,在该result.txt文件中,我有如下模式: Statement | error | Declaration | file | msg --- | PQ | * | first.txt | This is coming due to the file di

我有一个名为result.txt的文件,在该result.txt文件中,我有如下模式:

Statement                       | error         | Declaration      | file         | msg 
---                             | PQ            | *                | first.txt    | This is coming due to the file differences
---                             | PQ            | *                | second.txt   | This is a expected error
---                             | NS            | *                | brown.txt    | This errors need to be fixed from the source file
expected logic is extended      | TP            | *                | green.txt    | This is directly coming from the source file
unexpected logic is seen here   | TNP           | *                | red.txt      | This is coming from the output file 
extended logic expected         | CN            | *                | blue.txt     | This is a expected case
我需要将输出显示为错误是什么,特定错误重复了多少次,以及最后所有错误的总数,如下所示:

result.txt:
PQ : 2
NS : 1
TP : 1
TNP: 1
CN : 1
Total number of errors : 6
我尝试了以下代码,但没有得到所需的输出:

#!/bin/bash
for d in result.txt
do
echo "$d:";
awk '{ print $3 }' result.txt
echo "";
done
使用GNU awk:

awk 'BEGIN{FS=" \\| "; OFS=" : "} NR>1{gsub(/ +$/, "", $2); count[$2]++} END{for(j in count) printf("%-3s%s%d\n", j, OFS, count[j]); print "Total number of errors", NR-1 }' file
输出:

CN : 1 NS : 1 PQ : 2 TNP : 1 TP : 1 Total number of errors : 6 FS=\\\\:将输入字段分隔符设置为

OFS=::将输出字段分隔符设置为:

NR>1:忽略第一行

gsub/+$/,$2:从第2列中删除尾随空格

计数[$2]++:将列2保存为哈希/关联数组的键,并将其频率作为其值递增

forj in count:循环哈希计数以输出其内容

请参阅:

使用GNU awk:

awk 'BEGIN{FS=" \\| "; OFS=" : "} NR>1{gsub(/ +$/, "", $2); count[$2]++} END{for(j in count) printf("%-3s%s%d\n", j, OFS, count[j]); print "Total number of errors", NR-1 }' file
输出:

CN : 1 NS : 1 PQ : 2 TNP : 1 TP : 1 Total number of errors : 6 FS=\\\\:将输入字段分隔符设置为

OFS=::将输出字段分隔符设置为:

NR>1:忽略第一行

gsub/+$/,$2:从第2列中删除尾随空格

计数[$2]++:将列2保存为哈希/关联数组的键,并将其频率作为其值递增

forj in count:循环哈希计数以输出其内容

见:

F=|将列分隔符设置为|

开始{getline}跳过标题行

a[$2]++使用名为a的数组对第2列中的值进行计数

结束{..}打印结果

F=|将列分隔符设置为|

开始{getline}跳过标题行

a[$2]++使用名为a的数组对第2列中的值进行计数


结束{..}打印结果。

另一种类似的方法,只对输出格式使用暴力,而不是设置输出记录分隔符,类似于:

awk -F'|' '
    NR > 1 { gsub(/ *$/,"",$2 ); a[$2]++ }
    END    { for (i in a) {
                 n = n + a[i]
                 printf "%-4s: %d\n", i, a[i]
             }
             printf "Total number of errors : %d\n", n}
' errors
其中,对于大于1的所有记录(不是标题记录),删除字段中的所有尾随空格,并在该元素处向数组添加[]和增量值

在结束规则中,您只需循环所有字段作为数组中的索引,输出符号和相关错误数。将同一循环中的错误相加,单位为n

示例使用/输出

当您在文件错误中输入时,您只需选择复制上面的表达式并在终端中单击鼠标中键粘贴即可检查结果,例如

$ awk -F'|' '
>     NR > 1 { gsub(/ *$/,"",$2 ); a[$2]++ }
>     END    { for (i in a) {
>                     n = n + a[i]
>                     printf "%-4s: %d\n", i, a[i]
>                 }
>                 printf "Total number of errors : %d\n", n}
> ' errors
 CN : 1
 NS : 1
 PQ : 2
 TNP: 1
 TP : 1
Total number of errors : 6
注意:输出中的每个符号前都留有前导空格。如果您不希望它出现在那里,那么@Cyrus使用的substr将毫不费力地删除它们。或者,您可以简单地从gsub正则表达式中删除除空格以外的所有内容

格式仅在printf格式字符串中处理。但请注意@Cyrus用like标记的特殊变量。在复杂情况下,它们可以提供更短、更优雅的解决方案


如果您还有其他问题,请告诉我。

另一种类似的方法,即对输出格式使用暴力,而不是设置输出记录分隔符,类似于:

awk -F'|' '
    NR > 1 { gsub(/ *$/,"",$2 ); a[$2]++ }
    END    { for (i in a) {
                 n = n + a[i]
                 printf "%-4s: %d\n", i, a[i]
             }
             printf "Total number of errors : %d\n", n}
' errors
其中,对于大于1的所有记录(不是标题记录),删除字段中的所有尾随空格,并在该元素处向数组添加[]和增量值

在结束规则中,您只需循环所有字段作为数组中的索引,输出符号和相关错误数。将同一循环中的错误相加,单位为n

示例使用/输出

当您在文件错误中输入时,您只需选择复制上面的表达式并在终端中单击鼠标中键粘贴即可检查结果,例如

$ awk -F'|' '
>     NR > 1 { gsub(/ *$/,"",$2 ); a[$2]++ }
>     END    { for (i in a) {
>                     n = n + a[i]
>                     printf "%-4s: %d\n", i, a[i]
>                 }
>                 printf "Total number of errors : %d\n", n}
> ' errors
 CN : 1
 NS : 1
 PQ : 2
 TNP: 1
 TP : 1
Total number of errors : 6
注意:输出中的每个符号前都留有前导空格。如果您不希望它出现在那里,那么@Cyrus使用的substr将毫不费力地删除它们。或者,您可以简单地从gsub正则表达式中删除除空格以外的所有内容

格式仅在printf格式字符串中处理。但请注意@Cyrus用like标记的特殊变量。在复杂情况下,它们可以提供更短、更优雅的解决方案


如果您还有其他问题,请告诉我。

这纯粹是awk的问题。删除bash标记,然后这是否回答了您的问题@不,实际上我的文件模式有点不同。你可以通过弄清楚如何在awk中使用|作为分隔符来解决这个问题。这纯粹是awk的问题。删除bash标记,然后这是否回答了您的问题@不,事实上我的文件模式有点不同。你可以通过弄清楚如何使用|作为awk@Cyrus我得到的输出是这样的:errors:second.txt:1first.txt:1green.txt:1blue.txt:1tnp |*:1brown.txt:1错误总数:6。@Rama:我现在无法重现。请将您的文件上传到某个地方,并在此处共享链接。@Cyrus我得到的输出如下:errors:second.txt:1 first.txt:1 green.txt:1 blue.txt:1 TNP |*:1 brown.txt:1错误总数:6。@Rama:我目前无法重现。请将您的文件上传到某个地方并在此处共享链接。谢谢,它工作得很好,但是开始{getline}是跳过第一个l
伊恩,我们能跳过前两行吗?@Rama:BEGIN{getline;getline}谢谢,它工作得很好,但是BEGIN{getline}就是跳过第一行,我们能跳过前两行吗?@Rama:BEGIN{getline;getline}