我做错了什么?没有用awk正确排序

时间:2016-10-20 01:23:01

标签: awk

嗨,所以基本上我有一个' temp'我使用的文本文件有很长的各种电子邮件地址列表(一些重复)。我尝试输出的是最高频率的电子邮件地址,然后是最后的唯一电子邮件地址总数。

awk '{printf "%s %s\n", $2, $1} END {print "total "NR}' temp | sort -n | uniq -c -i

到目前为止,我得到了我想要的输出,除了,因为它没有按照最高频率排序。相反,它按字母顺序排列。

我已经被困在这几个小时了,不知道为什么。我知道我可能做错了什么,但我不确定。如果您需要更多信息并且我提供的代码不是问题,请告诉我。提前谢谢。

编辑:我也尝试过排序-nk1(输出在第一列有频率)和偶数-nk2

edit2:以下是我的“临时”的示例。文件

aol.com
netscape.net
yahoo.com
yahoo.com
adelphia.net
twcny.rr.com
charter.net
yahoo.com

编辑3:

预期产出:

33 aol.com
24 netscape.net
18 yahoo.com
5 adelphia.net
4 twcny.rr.com
3 charter.net
total 6

(不重复电子邮件,6个唯一的电子邮件地址)

3 个答案:

答案 0 :(得分:2)

修改了示例输入以包含具有两个实例的电子邮件

$ cat ip.txt 
aol.com
netscape.net
yahoo.com
yahoo.com
adelphia.net
twcny.rr.com
netscape.net
charter.net
yahoo.com

使用perl

$ perl -lne '
$c++ if !$h{$_}++;
END
{
    @k = sort { $h{$b} <=> $h{$a} } keys %h;
    print "$h{$_} $_" foreach (@k);
    print "total ", $c;
}' ip.txt
3 yahoo.com
2 netscape.net
1 adelphia.net
1 charter.net
1 aol.com
1 twcny.rr.com
total 6
  • $c++ if !$h{$_}++增量计数器用于唯一输入行,以输入行为键增加哈希值。
  • 的默认初始值为0
  • 处理完所有输入行后:
    • @k = sort { $h{$b} <=> $h{$a} } keys %h获取按哈希值降序排序的键
    • print "$h{$_} $_" foreach (@k)根据排序的密钥@k
    • 打印每个哈希值和密钥
    • print "total ", $c打印总行数


如果愿意,可以用单行写成:

perl -lne '$c++ if !$h{$_}++; END{@k = sort { $h{$b} <=> $h{$a} } keys %h; print "$h{$_} $_" foreach (@k); print "total ", $c}' ip.txt


参考: How to sort perl hash on values and order the keys correspondingly

答案 1 :(得分:2)

在Gnu awk中使用@Sundeep的数据:

$ cat program.awk
{ a[$0]++ }                                # count domains 
END {
    PROCINFO["sorted_in"]="@val_num_desc"  # sort in desc order in for loop
    for(i in a) {                          # this for in desc order
        print a[i], i 
        j++                                # count total
    } 
    print "total", j
}

运行它:

$ awk -f program.awk ip.txt
3 yahoo.com
2 netscape.net
1 twcny.rr.com
1 aol.com
1 adelphia.net
1 charter.net
total 6

答案 2 :(得分:1)

更新/摘要

总结了这个方便的分类工具的一些测试方法:

使用bash (在我的情况下为v4.3.46)

sortedfile="$(sort temp)" ; countedfile="$(uniq -c <<< "$sortedfile")" ; uniquefile="$(sort -rn <<< "$countedfile")" ; totalunique="$(wc -l <<< "$uniquefile")" ; echo -e "$uniquefile\nTotal: $totalunique"

使用sh/ash/busybox (虽然它们并非全部相同,但它们在这些测试中的工作方式相同)

time (sort temp > /tmp/sortedfile ; uniq -c /tmp/sortedfile > /tmp/countedfile ; sort -rn /tmp/countedfile > /tmp/uniquefile ; totalunique="$(cat /tmp/uniquefile | wc -l)" ; cat /tmp/uniquefile ; echo "Total: $totalunique")

使用perl (请参阅此回答https://stackoverflow.com/a/40145395/3544399

perl -lne '$c++ if !$h{$_}++; END{@k = sort { $h{$b} <=> $h{$a} } keys %h; print "$h{$_} $_" foreach (@k); print "Total: ", $c}' temp

测试了什么

使用随机生成器创建文件temp

  • @ domain.com在唯一地址中有所不同
  • 重复的地址分散
  • 文件 55304 总地址
  • 文件有 17012 重复的地址

该文件的一小部分示例如下:

24187@9674.com
29397@13000.com
18398@27118.com
23889@7053.com
24501@7413.com
9102@4788.com
16218@20729.com
991@21800.com
4718@19033.com
22504@28021.com

性能:

为了完整起见,值得一提的是表现;

perl:               sh:                 bash:

Total: 17012        Total:    17012     Total:    17012

real    0m0.119s    real    0m0.838s    real    0m0.973s
user    0m0.061s    user    0m0.772s    user    0m0.894s
sys     0m0.027s    sys     0m0.025s    sys     0m0.056s

原始答案(计算总地址而非唯一地址):

tcount="$(cat temp | wc -l)" ; sort temp | uniq -c -i | sort -rn ; echo "Total: $tcount"
  • tcount="$(cat temp | wc -l)":使用行数生成变量
  • sort temp:为uniq
  • 准备的群组电子邮件地址
  • uniq -c -i:计算允许案例变化的事件
  • sort -rn:根据数字排序进行排序并颠倒顺序(最高位置)
  • echo "Total: $tcount":显示底部的总地址

示例临时文件

john@domain.com
john@domain.com
donald@domain.com
john@domain.com
sam@domain.com
sam@domain.com
bill@domain.com
john@domain.com
larry@domain.com
sam@domain.com
larry@domain.com
larry@domain.com
john@domain.com

示例输出:

   5 john@domain.com
   3 sam@domain.com
   3 larry@domain.com
   1 donald@domain.com
   1 bill@domain.com
Total:       13

修改:请参阅以下有关sort

使用的评论