我有一个文件,其中包含按以下顺序的 IP 地址和端口号:
IP地址:端口
1.1.1.1:21
1.1.1.1:22
2.2.2.2:443
3.3.3.3:80
3.3.3.3:443
我需要以下格式的结果
ipaddress : port, port
1.1.1.1:21,22
2.2.2.2:443
3.3.3.3:80,443
答案1
假设输入文件中的行没有尾随空格:
$ awk -F ':' 'BEGIN { OFS=FS } $1 in ports { ports[$1] = ports[$1] "," $2; next } { ports[$1] = $2 } END { for (ip in ports) print ip, ports[ip] }' file
3.3.3.3:80,443
1.1.1.1:21,22
2.2.2.2:443
剧本awk
,
BEGIN { OFS=FS }
$1 in ports { ports[$1] = ports[$1] "," $2; next }
{ ports[$1] = $2 }
END { for (ip in ports) print ip, ports[ip] }
首先将输出字段分隔符设置为与输入字段分隔符相同,输入字段分隔符是一个:
字符(在命令行上用 给出-F ':'
),然后它会测试当前的第一个字段(IP 地址)是否是键数组ports
。如果是,则将端口号(第二个字段)添加为该数组条目的逗号作为分隔符。如果不是,则数组中的条目将简单地设置为该 IP 地址的端口号。
最后,所有存储的 IP 地址都将与其收集的端口号一起打印。
答案2
datamash -t: -s groupby 1 collapse 2 < file
如果您的数据已经排序,则可以省略-s
.
或者在 Perl 中的散列中使用匿名数组:
$ perl -F: -lne '
push @{ $h{$F[0]} }, $F[1]
}{
for $k (sort keys %h) {print "$k:", join ",", @{ $h{$k}} }
' file
1.1.1.1:21,22
2.2.2.2:443
3.3.3.3:80,443
答案3
使用米勒(http://johnkerl.org/miller/doc) 是
mlr --nidx --fs ':' nest --implode --values --across-records --nested-fs "," -f 2 input
它给你回馈
1.1.1.1:21,22
2.2.2.2:443
3.3.3.3:80,443
答案4
您可以使用sed
编辑器来完成。我们在模式空间中随时维护 2 条线,并查找 IP 号的变化。只要我们继续获得相同的 IP,我们就会从第二部分中删除该 IP,并用逗号将其与第一部分连接起来。如果没有,则意味着已检测到 IP 更改,我们立即仅打印第一部分,将其从模式空间中删除,然后返回并将下一个 IP 行读入模式空间并重复相同的检查。
$ sed -e '
:loop
$!N
s/^\(\([^:]*:\).*[^[:space:]]\).*\n\2/\1,/
tloop
P;D
' input-file.txt
1.1.1.1:21,22
2.2.2.2:443
3.3.3.3:80,443
$ perl -lne '
my($ip, $port) = /(\H+):(\H+)/;
push @seen, $ip if ! exists $h{$ip};
push @{$h{$ip}}, $port;}{
print $_, ":", join ",", @{$h{$_}} for @seen;
' input-file.txt
使用 Perl,我们可以通过散列来执行相同的操作,该散列将维护 IP 作为其键,并将数组引用作为包含端口的值。此外,我们确保不考虑任何尾随空格。数组 @seen 按照 IP 出现的顺序维护它们。