按重复次数排序

发布于 2024-12-21 14:25:11 字数 510 浏览 0 评论 0原文

我有一个如下所示的文件:

192.168.2.2 150.25.45.7 8080
192.168.12.25 178.25.45.7 50
192.168.2.2 142.55.45.18 369
192.168.489.2 122.25.35.7 8080
192.168.489.2 90.254.45.7 80
192.168.2.2 142.55.45.18 457

我编了所有数字。

我需要根据第一个ip的重复次数对所有这些文件进行排序。因此,理想情况下,输出应如下所示:

192.168.2.2 8080 369 457 3
192.168.489.2 8080 80 2
192.168.12.25 50 1

所以:第一个 ip、与第一个 ip 一致的所有端口以及重复次数。

我一直在尝试使用 sort 命令和 awk,但我不想做额外的工作,并且可能会错过其他一些简单的解决方案。

有什么想法吗?谢谢 :)

I have a file that looks like this:

192.168.2.2 150.25.45.7 8080
192.168.12.25 178.25.45.7 50
192.168.2.2 142.55.45.18 369
192.168.489.2 122.25.35.7 8080
192.168.489.2 90.254.45.7 80
192.168.2.2 142.55.45.18 457

I made up all the numbers.

I need to sort all these files according to the number of repetitions of the first ip. So the output would ideally look like this:

192.168.2.2 8080 369 457 3
192.168.489.2 8080 80 2
192.168.12.25 50 1

So: first ip, all the ports that were in lines with that first ip, and the number of repetitions.

I've been trying to play with the sort command and awk but I don't want to do extra work and maybe be missing out on some other straightforward solution.

Any idea? Thanks :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

对你而言 2024-12-28 14:25:11

Perlish 的答案看起来像这样。

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;

my %data;

# Store IP address and port number
while (<DATA>) {
  chomp;
  my ($ip, undef, $port) = split;
  push @{$data{$ip}}, $port;
}

# Sort (in reverse) by length of list of ports
for (sort { @{$data{$b}} <=> @{$data{$a}} } keys %data) {
  say "$_ @{$data{$_}} ", scalar @{$data{$_}};
}

__DATA__
192.168.2.2 150.25.45.7 8080
192.168.12.25 178.25.45.7 50
192.168.2.2 142.55.45.18 369
192.168.489.2 122.25.35.7 8080
192.168.489.2 90.254.45.7 80
192.168.2.2 142.55.45.18 457

输出:

192.168.2.2 8080 369 457 3
192.168.489.2 8080 80 2
192.168.12.25 50 1

A Perlish answer would look something like this.

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;

my %data;

# Store IP address and port number
while (<DATA>) {
  chomp;
  my ($ip, undef, $port) = split;
  push @{$data{$ip}}, $port;
}

# Sort (in reverse) by length of list of ports
for (sort { @{$data{$b}} <=> @{$data{$a}} } keys %data) {
  say "$_ @{$data{$_}} ", scalar @{$data{$_}};
}

__DATA__
192.168.2.2 150.25.45.7 8080
192.168.12.25 178.25.45.7 50
192.168.2.2 142.55.45.18 369
192.168.489.2 122.25.35.7 8080
192.168.489.2 90.254.45.7 80
192.168.2.2 142.55.45.18 457

Output:

192.168.2.2 8080 369 457 3
192.168.489.2 8080 80 2
192.168.12.25 50 1
本王不退位尔等都是臣 2024-12-28 14:25:11

Perl 方式:

#!/usr/bin/perl
use strict;
use warnings;

my %repeat;
while(<DATA>) {
    if (/^(\d+(?:.\d+){3})\s\S+\s(\d+)$/) {
        push @{$repeat{$1}}, $2;
    }
}
foreach (sort {@{$repeat{$b}}<=>@{$repeat{$a}}} keys %repeat) {
    my $num = @{$repeat{$_}};
    print "$_ @{$repeat{$_}} $num\n";
}

__DATA__
192.168.2.2 150.25.45.7 8080
192.168.12.25 178.25.45.7 50
192.168.2.2 142.55.45.18 369
192.168.489.2 122.25.35.7 8080
192.168.489.2 90.254.45.7 80
192.168.2.2 142.55.45.18 457

输出:

192.168.2.2 8080 369 457 3
192.168.489.2 8080 80 2
192.168.12.25 50 1

A Perl way:

#!/usr/bin/perl
use strict;
use warnings;

my %repeat;
while(<DATA>) {
    if (/^(\d+(?:.\d+){3})\s\S+\s(\d+)$/) {
        push @{$repeat{$1}}, $2;
    }
}
foreach (sort {@{$repeat{$b}}<=>@{$repeat{$a}}} keys %repeat) {
    my $num = @{$repeat{$_}};
    print "$_ @{$repeat{$_}} $num\n";
}

__DATA__
192.168.2.2 150.25.45.7 8080
192.168.12.25 178.25.45.7 50
192.168.2.2 142.55.45.18 369
192.168.489.2 122.25.35.7 8080
192.168.489.2 90.254.45.7 80
192.168.2.2 142.55.45.18 457

output:

192.168.2.2 8080 369 457 3
192.168.489.2 8080 80 2
192.168.12.25 50 1
想念有你 2024-12-28 14:25:11

另一个 Perl 解决方案:

#!/usr/bin/perl

use strict;
use warnings;

my %ips;
push @{$ips{$_->[0]}}, $_->[1]+0 for map{[split/ \S+ /]}<DATA>;

for (sort {@{$ips{$b}} <=> @{$ips{$a}}} keys %ips) {
    printf("%s %s %d\n", $_, join(" ", @{$ips{$_}}), 0+@{$ips{$_}});
}

__DATA__
192.168.2.2 150.25.45.7 8080
192.168.12.25 178.25.45.7 50
192.168.2.2 142.55.45.18 369
192.168.489.2 122.25.35.7 8080
192.168.489.2 90.254.45.7 80
192.168.2.2 142.55.45.18 457

输出:

192.168.2.2 8080 369 457 3
192.168.489.2 8080 80 2
192.168.12.25 50 1

Another Perl solution:

#!/usr/bin/perl

use strict;
use warnings;

my %ips;
push @{$ips{$_->[0]}}, $_->[1]+0 for map{[split/ \S+ /]}<DATA>;

for (sort {@{$ips{$b}} <=> @{$ips{$a}}} keys %ips) {
    printf("%s %s %d\n", $_, join(" ", @{$ips{$_}}), 0+@{$ips{$_}});
}

__DATA__
192.168.2.2 150.25.45.7 8080
192.168.12.25 178.25.45.7 50
192.168.2.2 142.55.45.18 369
192.168.489.2 122.25.35.7 8080
192.168.489.2 90.254.45.7 80
192.168.2.2 142.55.45.18 457

Output:

192.168.2.2 8080 369 457 3
192.168.489.2 8080 80 2
192.168.12.25 50 1
晚雾 2024-12-28 14:25:11

此行应该可以为您完成工作:

awk '{a[$1]++;b[$1]=b[$1]" "$3}END{for(x in a)print a[x]"\t"x,b[x],a[x]}' input |
sort -nr|cut -f2-

用您的示例测试

kent$  cat tt
192.168.2.2 150.25.45.7 8080
192.168.12.25 178.25.45.7 50
192.168.2.2 142.55.45.18 369
192.168.489.2 122.25.35.7 8080
192.168.489.2 90.254.45.7 80
192.168.2.2 142.55.45.18 457

kent$  awk '{a[$1]++;b[$1]=b[$1]" "$3}END{for(x in a)print a[x]"\t"x,b[x],a[x]}' tt |
sort -nr|cut -f2-
192.168.2.2  8080 369 457 3
192.168.489.2  8080 80 2
192.168.12.25  50 1

this line should do the job for you:

awk '{a[$1]++;b[$1]=b[$1]" "$3}END{for(x in a)print a[x]"\t"x,b[x],a[x]}' input |
sort -nr|cut -f2-

test with your example

kent$  cat tt
192.168.2.2 150.25.45.7 8080
192.168.12.25 178.25.45.7 50
192.168.2.2 142.55.45.18 369
192.168.489.2 122.25.35.7 8080
192.168.489.2 90.254.45.7 80
192.168.2.2 142.55.45.18 457

kent$  awk '{a[$1]++;b[$1]=b[$1]" "$3}END{for(x in a)print a[x]"\t"x,b[x],a[x]}' tt |
sort -nr|cut -f2-
192.168.2.2  8080 369 457 3
192.168.489.2  8080 80 2
192.168.12.25  50 1
浮光之海 2024-12-28 14:25:11

这是一个主要依赖 awk 和 sort 的管道:

sort -k1 -k3n \
| awk -F' ' '
    NR==1 { 
      printf("%s ", $1); 
      current = $1 
    } 
    $1 != current { 
      printf(":%d\n%s ", count, $1); 
      current = $1; 
      count = 0 
    } 
    { printf("%d ", $3); count++ } 
    END { printf(":%d\n", count) }' \
| sort -t':' -k2nr \
| tr -d':'

Here's a pipeline relying mainly on awk and sort:

sort -k1 -k3n \
| awk -F' ' '
    NR==1 { 
      printf("%s ", $1); 
      current = $1 
    } 
    $1 != current { 
      printf(":%d\n%s ", count, $1); 
      current = $1; 
      count = 0 
    } 
    { printf("%d ", $3); count++ } 
    END { printf(":%d\n", count) }' \
| sort -t':' -k2nr \
| tr -d':'
亽野灬性zι浪 2024-12-28 14:25:11

GNU awk 4:

awk 'END {
  PROCINFO["sorted_in"] = "@val_num_desc"
  for (e in ic)
    print e, ip[e], ic[e] 
  }
{
  ip[$1] = $1 in ip ? ip[$1] OFS $NF : $NF
  ic[$1]++
  }' infile

GNU awk 4:

awk 'END {
  PROCINFO["sorted_in"] = "@val_num_desc"
  for (e in ic)
    print e, ip[e], ic[e] 
  }
{
  ip[$1] = $1 in ip ? ip[$1] OFS $NF : $NF
  ic[$1]++
  }' infile
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文