我有两个文件,一个名为NATLog,有3列,另一个是Sourceports,有2列,下面是NATLog文件的示例。
14 172.18.2.12 445
50 172.18.24.4 123
80 10.2.123.37 22
68 172.18.1.37 25
我想将NATLog文件的最后一列与Sourceports文件的第一列匹配,并将关联的服务作为第4列附加到NATLog文件
445 SMB
123 Network Time Protocol (NTP)
22 SSH
25 SMTP(Insecure)
14 172.18.2.12 445 SMB
50 172.18.24.4 123 Network Time Protocol (NTP)
80 10.2.123.37 22 SSH
68 172.18.1.37 25 SMTP(Insecure)
我正在努力学习AWK来实现这一目标,但我需要一些帮助,请你帮助我,谢谢
试试awk,
$ awk ' NR==FNR {x=$1; $1="";a[x]=$0; next } { print $0, a[$3] } ' Sourceports NATLog
14 172.18.2.12 445 SMB
50 172.18.24.4 123 Network Time Protocol (NTP)
80 10.2.123.37 22 SSH
68 172.18.1.37 25 SMTP(Insecure)
$
awk中的另一个(实际上是两个)。这是完美的世界:
$ awk 'NR==FNR{a[$1]=$0;next}{sub($NF,a[$NF])}1' source natlog
14 172.18.2.12 445 SMB
50 172.18.24.4 123 Network Time Protocol (NTP)
80 10.2.123.37 22 SSH
68 172.18.1.37 25 SMTP(Insecure)
解释(并为不完美的世界稍微扩展):
$ awk '
NR==FNR { # processing the source file
# gsub(/&/,"\\\\&") # if & chars in the file, uncomment to escape them
a[$1]=$0 # hash to a, port is the key
next
}
{ # process natlog file
sub($NF,a[$NF]) # replace port field with entry from source file
# sub($NF,(a[$NF]?a[$NF]:$NF)) # if gaps in source, use this instead of above
}1' source natlog
一个可能的输出(较短的ip,&
char在源和不匹配的端口222):
14 1.18.2.12 445 SMB &
50 172.18.24.4 123 Network Time Protocol (NTP)
80 10.2.123.37 222
68 172.18.1.37 25 SMTP(Insecure)
awk '
NR==FNR { key=$1; sub(/[^[:space:]]+[[:space:]]+/,""); map[key]=$0; next }
{ print $0, map[$3] }
' Sourceports NATLog
如果你的目标是以协调方式附加的协议列显示的输出格式,那么printf
而不是print
提供了man 3 printf
中描述的相同的细粒度格式控制(大多数情况下)。在您的情况下,您只需要获取端口号字段的length()
并从所需的总字段宽度中减去该值,以便在从NATLog
附加保存的协议之前在Sourceports
记录之后添加许多空格。
您可以使用类似于以下内容的方法,其中总字段宽度为4用作示例:
$ awk '
NR==FNR {pcl[$1] = $2; next} {printf "%s%*s%s\n",$0,4-length($3)," ",pcl[$3]}
' Sourceports NATLog
产量
14 172.18.2.12 445 SMB
50 172.18.24.4 123 Network
80 10.2.123.37 22 SSH
68 172.18.1.37 25 SMTP(Insecure)
(注意:你的Sourceports
在记录的末尾不能包含额外的空格。如果是,那么你将不得不用单独的$0
替换$1,$2,$3
并相应地调整格式字符串)
通常有很多方法可以在awk
中完成同样的事情,因此您可以根据自己的需要量身定制它。
使用paste
和awk
较短但效率较低的方法是使用paste
和awk
来实现同样的目的。 (基本上只输出NATLog
的前两个字段,并用Sourceports
附加paste
的内容,例如
$ paste -d ' ' <(awk '{print $1, $2}' NATLog) Sourceports
14 172.18.2.12 445 SMB
50 172.18.24.4 123 Network Time Protocol (NTP)
80 10.2.123.37 22 SSH
68 172.18.1.37 25 SMTP(Insecure)
(但那真的会打败学习awk
的目的)
这就是为什么linux有一些小工具,如cat
,cut
,paste
,在这种情况下join
。
join -1 3 -2 1 natlog source
加入适用于您尝试使用join
的列进行排序的文件。
排序实际上是一个有点错误的措辞。它应该更像是等价的。正如您所注意到的,您的文件具有相同的输入和输出,并且您尝试使用join
的列是等效的。所以join
将毫无问题地工作。
如果两个文件都没有等效排序,您可以事先使用sort:
join -1 3 -2 1 <(sort -k3 natlog) <(sort source)
或者如果你只想坚持一个程序,那么awk
就是前进的方向:
awk '(NR==FNR){k=$3; $3=""; a[k]=$0; next}{ print $0,a[$1] }' natlog source
但如果natlog
和source
没有相同数量的线和/或键,那么你得到的共同部分是
awk '(NR==FNR){k=$3; $3=""; a[k]=$0; next}($1 in a){ print $0,a[$1] }' natlog source