我想根据每一行的内容对文件执行两种不同的排序和计数。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位数字开始的,但这次,保持整列的值并按其排序。
我尝试过的:以^\d\d\d和开头的行的| sort | uniq -c | sort -nr
对于那些不满足上述正则表达式的正则表达式也是如此,但有没有更优雅的方法使用sed
或awk
?
$ 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
您可以尝试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
第1版:
$ 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
$