附加

附加

我有一个包含 3 列的 TSV 制表符分隔文件:

ID\tTEXT\tTYPE

打印TYPE我做的专栏

cat /dataset.csv | awk -F $'\t' '{print $3}'

这些值是诸如 等值的枚举{CLASS_A,CLASS_B,CLASS_C}

当匹配枚举中的每个值时,我需要使用 AWK 的内联方式来计算列NF的出现次数(?)以获得:TYPE

CLASS_A 1300
CLASS_B 450
CLASS_C 988

[更新]

根据下面的解决方案,我把这个脚本的最后一个版本放在这里

#!/bin/bash

COL=$1
FILE=$2

awk -v col="$COL" -F $'\t' '   {c[$col]++}
                 END{
                     for (i in c) printf("%s\t%s\n",i,c[i])
                 }' $FILE

计算第 3 列中行出现次数的用法是

$ ./count_cols.sh 3 /myfile.csv

答案1

无需使用cat来读取文件。 AWK 完全能够读取它。

核心c[$3]++语句应该获取每种类型的行数。
然后,最后,只需打印(作为制表符分隔值)所有计数:

#!/bin/bash

awk -F '\t' '   {c[$3]++}
                 END{
                     for (i in c) printf("%s\t%s\n",i,c[i])
                 }' dataset.csv 

附加

鉴于OP的评论是:

对于带有引号的列,我遇到一些问题,例如that doesn\'t mean that you\'re not worth remembering think of the people who need to know they need to know so you need ​to show....In this case the parsing on \t will failure.

我必须回顾一下答案。我创建了这个文件:

$ cat dataset.csv 
1233    that doesn\'t mean that you\'re not worth remembering think of the people who need to know they need to know so you need to show...    CLASS_0
1234    here    CLASS_A
1235    goes the values CLASS_B
1236    "that need counting"    CLASS_B
1237    "\like \this"   CLASS_B
1238    \or \this       CLASS_C
1239    including spaces        CLASS_B
1240    but not tabs    CLASS_A
1241    which could not work    CLASS_B
1242    finally CLASS_C
1243    this is CLASS_A
1244    over    CLASS_B
1245    988     CLASS_C

该文件与脚本一起使用时会给出正确的结果:

$ ./script
CLASS_A 3
CLASS_B 6
CLASS_C 3
CLASS_0 1

这是正确的结果。

当然,文件

  1. tabs具有3 个字段的正确数量,并且
  2. 变量在扩展时被正确引用并且不是大写的。

要测试文件是否符合第一个要求,您可以使用以下脚本:

#!/bin/bash

filetoread="$2"

<"$filetoread" tr -dc '\t\n' |
    awk '(length!=2){printf("Error in line: %s, has %s tabs\n",NR,length)}'

awk -F '\t' '(NF!=3){printf("Error in line: %s, has %s fields\n",NR,NF)}' "$filetoread"

它检查每行是否有两个制表符,并且
字段数(如 awk 所示)实际上是三个。

添加几行测试线:

… …
1239    including spaces        CLASS_B
1       but not     tabs    CLASS_A
2       but not \ttabs  CLASS_A
1240    but not tabs    CLASS_A
… …

并运行上面的脚本:

$ ./script 3 dataset.csv
Error in line: 8, has 4 tabs
Error in line: 8, has 5 fields

检测具有四个选项卡(添加了两个)的行 ID 1,并且不会被带有\t.

至于变量的引用和使用,那就需要你自己去改进了。

答案2

像这样的东西可以完成这项工作:

awk -F'\t' ' 
            $3=="CLASS_A" {a+=1} 
            $3=="CLASS_B" {b+=1} 
            $3=="CLASS_C" {c+=1} 
            END {
                printf "%s %d\n%s %d\n%s %d", CLASS_A,a,CLASS_B,b,CLASS_C,c
            }' /dataset.csv

答案3

我希望我正确理解第 3 列可以包含“CLASS_A”“CLASS_B”或“CLASS_C”?

然后

awk -F'\t'  '
 { seen[$3]++ ;}
 END { for (i in seen) {
         printf "%s : %s\n",i,seen[i]
       }
      } 
 ' /dataset.csv

应该做这件事吗?

请注意,“for (i in saw)”并不能保证它们以“正确的顺序”读取,但您可以添加一个| sort(在整个 awk 后面)对它们进行排序,或者使用更多复杂的技巧(在 awk 内) 。

如果您还需要跳过第一行(例如,如果它包含标题)添加awk 脚本第一行之前:

( NR==1 ) { next ;}

或按如下方式更改第一行:

( NR > 1 ) { seen[$3]++ ;}

相关内容