按shell中的出现对列进行排序

时间:2013-09-15 16:04:57

标签: shell unix

我是unix的新手。我正在尝试通过其中某个列中出现的值对文件进行排序:

IP    - - Website
1.1.1 - - stackoverflow.com
0.0.5 - - a.com 
1.1.1 - - google.com

预期结果:

IP    - - Website
1.1.1 - - stackoverflow.com
0.0.5 - - a.com

我尝试了不同的方法:

  • sort -k1 | uniq -c(由于uniq检查整行,包括网站,因此无效)
  • 使用sort -u -t- -k1

任何人都可以帮助我,或者至少告诉我,我做错了吗?

编辑:我发现了一种更好的方法: egrep -o'[[:digits:]] {1,3}。[[:digits:]] {1,3}。[[:digits:]] {1,3}'| sort -g | uniq -c | sort -gr(希望有一天能帮到某人)

4 个答案:

答案 0 :(得分:2)

您可以给机会。它基于中间的-分割两个字段中的行,并将内容保存在哈希中以便稍后对其进行排序。在散列中,键是IP,值是一个array-ref,其中包含每个IP外观和原始行的计数器。

假设infile包含内容:

IP    - - Website
2.2.2 - - yahoo.es
1.1.1 - - in.google.com
0.0.5 - - a.com 
1.1.1 - - google.com
1.1.1 - - gmail.google.com
2.2.2 - - yahoo.com

跟随perl命令:

perl -lne '
    do { $header = $_; next } if $. == 1;
    my @f = split /\s+-\s+-\s+/;
    if ( ! exists $ips{ $f[0] } ) {
        $ips{ $f[0] } = [ 1, $_ ];
    }
    else {
        $ips{ $f[0] }[0] += 1;
    }
    END {
        printf qq|%s\n|, $header;
        for my $key ( sort { $ips{ $b }[0] <=> $ips{ $a }[0] } keys %ips ) {
            printf qq|%s\n|, $ips{ $key }[1];
        }
    }
' infile

它产生:

IP    - - Website
1.1.1 - - in.google.com
2.2.2 - - yahoo.es
0.0.5 - - a.com

答案 1 :(得分:2)

您似乎要求删除任何包含重复的第一个字段的行。这可以通过以下awk一行来实现:

$ awk '!a[$1]++' file
IP    - - Website
1.1.1 - - stackoverflow.com
0.0.5 - - a.com

答案 2 :(得分:0)

简单的shell解决方案......

egrep -o '^[0-9\.]+' myfile.txt | sort | uniq -c | sort -nr

答案 3 :(得分:-1)

uniq可以在-w指定数量的字符后忽略其余行。

sort -r -k1 file | uniq -w5

uniq -w不是POSIX,但如果你碰巧在一个相当新的Linux上,它应该可以工作。

接下来,我被告知第一个字段与垂直对齐的示例不同,是可变长度。应该知道,这是一个IP地址,愚蠢! :)在这种情况下,我在IP地址后添加8个空格以补偿最短(7)和最长(15)变体之间的差异,告诉uniq忽略前15个字符,然后再将剩余的空格压缩为1 < / p>

sort -r -k1 file | sed 's/ /         /' | uniq -w15 | sed 's/  */ /'

没有Perl。