Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 使用列条件打印uniq后的行_Linux_Bash_Sorting_Awk_Uniq - Fatal编程技术网

Linux 使用列条件打印uniq后的行

Linux 使用列条件打印uniq后的行,linux,bash,sorting,awk,uniq,Linux,Bash,Sorting,Awk,Uniq,我有一个文件,其中包含以下内容 192.168.168.23 pg.something 181.135.56.13 pg.nothing 15.123.96.12 l.everything 15.151.15.3 f.something 15.151.15.3 pg.something 64.196.12.34 pg.nothing 15.123.96.12 l.everything 181.168.56.13 pg.nothing 192.168.168.23 pg.something 192

我有一个文件,其中包含以下内容

192.168.168.23 pg.something
181.135.56.13 pg.nothing
15.123.96.12 l.everything
15.151.15.3 f.something
15.151.15.3 pg.something
64.196.12.34 pg.nothing
15.123.96.12 l.everything
181.168.56.13 pg.nothing
192.168.168.23 pg.something
192.168.168.23 l.everything
192.12.56.152 l.everything
181.135.56.13 pg.nothing
64.196.12.34 pg.nothing
64.196.12.34 pg.something
181.135.56.13 pg.nothing
64.196.12.34 l.everything
我试图找出每个IP对每个IP排序的用户的点击数

我试过这个

for i in `cat test_file |awk '{print $1}'|sort |uniq -c |sort -rn |awk '{print $2}'`; do grep $i test_file;done |uniq -c |awk '{print $2,$3,$1}'
得到

64.196.12.34 pg.nothing 2
64.196.12.34 pg.something 1
64.196.12.34 l.everything 1
192.168.168.23 pg.something 2
192.168.168.23 l.everything 1
181.135.56.13 pg.nothing 3
15.151.15.3 f.something 1
15.151.15.3 pg.something 1
15.123.96.12 l.everything 2
192.12.56.152 l.everything 1
181.168.56.13 pg.nothing 1
这个输出很好。但我想知道是否有一种方法可以修改这个输出,使其看起来像这样

64.196.12.34 pg.nothing 2
             pg.something 1
             l.everything 1
192.168.168.23 pg.something 2
               l.everything 1
181.135.56.13 pg.nothing 3
15.151.15.3 f.something 1
            pg.something 1
15.123.96.12 l.everything 2
192.12.56.152 l.everything 1
181.168.56.13 pg.nothing 1
即仅删除重复的IP


提前感谢。

这是从头开始计算的:

awk '
     {a[$1,$2]++; b[$1]; c[$2]}
     END{for (i in b) {for (j in c) if (a[i,j]) print i,j,a[i,j]}}
    ' file | awk '
                  $1==prev {print FS $2 FS $3; next} {prev=$1; print}
                 '
第一部分计算: 解释
  • {a[$1,$2]++;b[$1];c[$2]}
    跟踪所有行组合:
    a
    存储第一个+第二个字段,
    b
    第一个和
    c
    第二个
  • END{for(i in b){for(j in c)if(a[i,j])print i,j,a[i,j]}
    在第一个和第二个字段中循环,只打印那些匹配的字段
并由此进行分组: 解释
  • '$1==prev{print FS$2 FS$3;next}
    如果前一行有相同的第一个字段,请仅从第二个字段打印
  • {prev=$1;print}'
    否则,正常打印

您可以使用以下命令修改上一个awk命令:

awk '{if ($2!=a) {print $2"\t"$3"\t"$1} else {print "\t\t"$3"\t"$1}}{a=$2}'
其中:

64.196.12.34    pg.nothing      2
                pg.something    1
                l.everything    1
192.168.168.23  pg.something    2
                l.everything    1
181.135.56.13   pg.nothing      3
15.151.15.3     f.something     1
                pg.something    1
15.123.96.12    l.everything    2
192.12.56.152   l.everything    1
181.168.56.13   pg.nothing      1

下面是一个Perl版本的解决方案:

#!/usr/bin/perl

use warnings;
use strict;

my %data;

while (<DATA>) {
    chomp;
    my ($ip, $dom) = split;
    $data{$ip}->{$dom}++;
}

while(my ($ip, $doms) = each %data) {
    print "$ip\t";
    my ($dom, $cnt) = each %$doms;
    print "$dom $cnt\n";
    while (($dom, $cnt) = each %$doms) {
        print "\t\t$dom $cnt\n";
    }
    print "\n";
}

__DATA__
192.168.168.23 pg.something
181.135.56.13 pg.nothing
15.123.96.12 l.everything
15.151.15.3 f.something
15.151.15.3 pg.something
64.196.12.34 pg.nothing
15.123.96.12 l.everything
181.168.56.13 pg.nothing
192.168.168.23 pg.something
192.168.168.23 l.everything
192.12.56.152 l.everything
181.135.56.13 pg.nothing
64.196.12.34 pg.nothing
64.196.12.34 pg.something
181.135.56.13 pg.nothing
64.196.12.34 l.everything
结果没有很好地对齐,但是应该很容易调整它,以提供与问题中完全相同的对齐

以下是经过改编的版本:

while(my ($ip, $doms) = each %data) {
    print "$ip ";
    my ($dom, $cnt) = each %$doms;
    print "$dom $cnt\n";
    my $prefix = ' ' x (length $ip);
    while (($dom, $cnt) = each %$doms) {
        print "$prefix $dom $cnt\n";
    }
}

谢谢它起作用了。正是我需要的。稍微调整一下。awk{if($2!=a){print$2”\t“$3”\t“$1}else{print”\t\t“$3”\t“$1}}{a=$2}。没有pb!接受答案吧!(感谢您的“=”,我将使用您的版本进行编辑)
#!/usr/bin/perl

use warnings;
use strict;

my %data;

while (<DATA>) {
    chomp;
    my ($ip, $dom) = split;
    $data{$ip}->{$dom}++;
}

while(my ($ip, $doms) = each %data) {
    print "$ip\t";
    my ($dom, $cnt) = each %$doms;
    print "$dom $cnt\n";
    while (($dom, $cnt) = each %$doms) {
        print "\t\t$dom $cnt\n";
    }
    print "\n";
}

__DATA__
192.168.168.23 pg.something
181.135.56.13 pg.nothing
15.123.96.12 l.everything
15.151.15.3 f.something
15.151.15.3 pg.something
64.196.12.34 pg.nothing
15.123.96.12 l.everything
181.168.56.13 pg.nothing
192.168.168.23 pg.something
192.168.168.23 l.everything
192.12.56.152 l.everything
181.135.56.13 pg.nothing
64.196.12.34 pg.nothing
64.196.12.34 pg.something
181.135.56.13 pg.nothing
64.196.12.34 l.everything
192.12.56.152   l.everything 1

15.151.15.3     pg.something 1
                f.something 1

64.196.12.34    pg.nothing 2
                pg.something 1
                l.everything 1

181.168.56.13   pg.nothing 1

15.123.96.12    l.everything 2

192.168.168.23  pg.something 2
                l.everything 1

181.135.56.13   pg.nothing 3
while(my ($ip, $doms) = each %data) {
    print "$ip ";
    my ($dom, $cnt) = each %$doms;
    print "$dom $cnt\n";
    my $prefix = ' ' x (length $ip);
    while (($dom, $cnt) = each %$doms) {
        print "$prefix $dom $cnt\n";
    }
}