计数,使用sed分组或awk

时间:2019-01-07 12:03:45

标签: awk sed

我想根据每一行的内容对文件执行两种不同的排序和计数。 1.我需要使用.tsv文件的第一列 我想按以三位数字开头的每一行进行分组,并且只保留前三位数字,对于其他所有内容,只需对第一列中句子的整个出现进行排序和计数即可。

样本数据:

687/878 9
890987  4
01a 55
1b  8743917
890a    34
abcdee  987
dfeqfe  fkdjald
890897  34213
6878853 834
32fasd  53891
abcdee  8794371
abd 873

结果:

687 2
890 3
01a 1
1b  1
32fasd  1
abd 1
dfeqfe  1
abcdee  2

我也希望解决方案

还考虑了示例输入

687/878 9
890987  4
01a     55
1b      8743917
890a    34
abcdee  987
dfeqfe  545
890897  34213
6878853 834
(632)fasd  53891
(88)abcdee  8794371
abd     873

因此第一列可能具有(,),#,'等所有字符的值

所以输出将有两列,第一列提取的值,第二列包含新的计数,并从源文件中提取新的值。

再次选择首选输出格式tsv。

所以我需要提取所有以 ^ \ d \ d \ d,然后对于这前三个数字,对唯一值进行排序和计数,

但是在第二遍中,也对每行执行相同的操作,该操作不是以3位数字开头,但是这一次,请保留整个列的值并以此为依据进行排序。

我尝试过的方法: | sort | uniq -c | sort -nr表示以^ \ d \ d \ d和

开头的行

对于不满足上述正则表达式的用户而言,是否相同,但是使用sedawk还是有更优雅的方式吗?

2 个答案:

答案 0 :(得分:2)

$ cat tst.awk
BEGIN { FS=OFS="\t" }
{ cnt[/^[0-9]{3}/ ? substr($1,1,3) : $1]++ }
END {
    for (key in cnt) {
        print (key !~ /^[0-9]{3}/), cnt[key], key, cnt[key]
    }
}

$ awk -f tst.awk file | sort -k1,2n | cut -f3-
687     1
890     2
abcdee  1

答案 1 :(得分:1)

您可以尝试Perl

$ cat nefijaka.txt
687     878     9
890987  4
890a    34
abcdee  987
$ perl -lne  ' /^(\d{3})|(\S+)/; $x=$1?$1:$2; $kv{$x}++; END { print "$_\t$kv{$_}" for (sort keys %kv) } ' nefijaka.txt
687     1
890     2
abcdee  1
$

您可以通过管道对其进行排序并获得排序的值。

$ perl -lne  ' /^(\d{3})|(\S+)/; $x=$1?$1:$2; $kv{$x}++; END { print "$_\t$kv{$_}" for (sort keys %kv) } ' nefijaka.txt | sort -k2 -nr
890     2
abcdee  1
687     1

EDIT1:

$ cat nefijaka.txt2
687     878     9
890987  4
890a    34
abcdee  987
a word and then 23
$ perl -lne  ' /^(\d{3})|(.+?\t)/; $x=$1?$1:$2; $x=~s/\t//g; $kv{$x}++; END { print "$_\t$kv{$_}" for (sort keys %kv) } ' nefijaka.txt2
687     1
890     2
a word and then 1
abcdee  1
$