从一行打印以 x 开头的某些单词
print certain words that begins with x from one line
我想以某种方式打印单词开头的单词,例如 srcip 和 srcintf,来自 /var/log/syslog
的这一行
Jul 21 13:13:35 some-name date=2020-07-21 time=13:13:34 devname="devicename" devid="deviceid" logid="0000000013" type="traffic" subtype="forward" level="notice" vd="root" eventtime=1595330014 srcip=1.2.3.4 srcport=57324 srcintf="someinterface" srcintfrole="wan" dstip=5.6.7.8 dstport=80 dstintf="anotherinterface" dstintfrole="lan" sessionid=supersecretid proto=6 action="deny" policyid=0 policytype="policy" service="HTTP" dstcountry="Sweden" srccountry="Sweden" trandisp="noop" duration=0 sentbyte=0 rcvdbyte=0 sentpkt=0 appcat="unscanned" crscore=30 craction=131072 crlevel="high"
看起来像这样的东西
date=2020-07-21 time=13:13:34 devname="devicename" action="deny" policyid=0 srcintf="someinterface" dstintf="anotherinterface" srcip=1.2.3.4 srcport=57324 -----> dstip=5.6.7.8 dstport=80
目前我正在使用 awk 来完成它。由于显而易见的原因,它的可扩展性非常差:
cat /var/log/syslog | awk '{print ,,,,,,,,,"-----> ",}'
也不是所有的行在同一个“字段”中都有 srcip。所以有些线真的歪了。
或者系统日志消息重写器是否更适合此目的?你将如何解决这个问题?提前致谢!
我为您提供了一个灵活的 awk 答案,而不是简单的单行代码,而是一种更具编程性的方式。您的日志文件中的行通常看起来像:
key1=value1 key2=value2 key3=value3 ...
这个awk的想法是把它分解成awk中的一个数组,它是关联的,这样元素就可以被称为:
a[key1]=>value1 a[key2]=>value2 ... a[key2,"full"]=>key2=value2 ...
使用 this answer 中解释的函数,您可以编写:
awk '
function str2map(str,fs1,fs2,map, n,tmp) {
n=split(str,map,fs1)
for (;n>0;n--) {
split(map[n],tmp,fs2);
map[tmp[1]]=tmp[2]; map[tmp[1],"full"]=map[n]
delete map[n]
}
}
{ str2map([=12=]," ","=",a) }
{ print a["date","full"],a["time","full"],a["devname","full"],a["action","full"] }
' file
这种方法非常灵活。在行的顺序或其他方面也没有依赖性。
注意: 上面的方法没有处理引用。因此,如果 space 出现在带引号的字符串中,它可能会把事情搞砸。
如果你有 filter.awk
:
BEGIN{
split(filter,a,",");
for (i in a){
f[a[i]]=1;
}
}
{
for (i=1; i<=NF; i++) {
split($i,b,"=");
if (b[1] in f){
printf("%s ", $i);
}
}
printf("\n");
}
你可以做到:
awk -v filter="srcip,srcintf" -f filter.awk /var/log/syslog
在您指定的过滤器中,以逗号分隔的关键字。它必须找到
注意:此脚本还假设文件的格式为:key1=value key2=value
并且值中没有 space。
$ cat tst.awk
{
delete f
for (i=5; i<=NF; i++) {
split($i,tmp,/=/)
f[tmp[1]] = $i
}
print f["date"], f["time"], f["devname"], f["action"], f["policyid"], f["srcintf"], \
f["dstintf"], f["srcip"], f["srcport"], "----->", f["dstip"], f["dstport"]
}
.
$ awk -f tst.awk file
date=2020-07-21 time=13:13:34 devname="devicename" action="deny" policyid=0 srcintf="someinterface" dstintf="anotherinterface" srcip=1.2.3.4 srcport=57324 -----> dstip=5.6.7.8 dstport=80
以上假定您引用的字符串不包含示例输入中所示的空格。
我想以某种方式打印单词开头的单词,例如 srcip 和 srcintf,来自 /var/log/syslog
的这一行Jul 21 13:13:35 some-name date=2020-07-21 time=13:13:34 devname="devicename" devid="deviceid" logid="0000000013" type="traffic" subtype="forward" level="notice" vd="root" eventtime=1595330014 srcip=1.2.3.4 srcport=57324 srcintf="someinterface" srcintfrole="wan" dstip=5.6.7.8 dstport=80 dstintf="anotherinterface" dstintfrole="lan" sessionid=supersecretid proto=6 action="deny" policyid=0 policytype="policy" service="HTTP" dstcountry="Sweden" srccountry="Sweden" trandisp="noop" duration=0 sentbyte=0 rcvdbyte=0 sentpkt=0 appcat="unscanned" crscore=30 craction=131072 crlevel="high"
看起来像这样的东西
date=2020-07-21 time=13:13:34 devname="devicename" action="deny" policyid=0 srcintf="someinterface" dstintf="anotherinterface" srcip=1.2.3.4 srcport=57324 -----> dstip=5.6.7.8 dstport=80
目前我正在使用 awk 来完成它。由于显而易见的原因,它的可扩展性非常差:
cat /var/log/syslog | awk '{print ,,,,,,,,,"-----> ",}'
也不是所有的行在同一个“字段”中都有 srcip。所以有些线真的歪了。
或者系统日志消息重写器是否更适合此目的?你将如何解决这个问题?提前致谢!
我为您提供了一个灵活的 awk 答案,而不是简单的单行代码,而是一种更具编程性的方式。您的日志文件中的行通常看起来像:
key1=value1 key2=value2 key3=value3 ...
这个awk的想法是把它分解成awk中的一个数组,它是关联的,这样元素就可以被称为:
a[key1]=>value1 a[key2]=>value2 ... a[key2,"full"]=>key2=value2 ...
使用 this answer 中解释的函数,您可以编写:
awk '
function str2map(str,fs1,fs2,map, n,tmp) {
n=split(str,map,fs1)
for (;n>0;n--) {
split(map[n],tmp,fs2);
map[tmp[1]]=tmp[2]; map[tmp[1],"full"]=map[n]
delete map[n]
}
}
{ str2map([=12=]," ","=",a) }
{ print a["date","full"],a["time","full"],a["devname","full"],a["action","full"] }
' file
这种方法非常灵活。在行的顺序或其他方面也没有依赖性。
注意: 上面的方法没有处理引用。因此,如果 space 出现在带引号的字符串中,它可能会把事情搞砸。
如果你有 filter.awk
:
BEGIN{
split(filter,a,",");
for (i in a){
f[a[i]]=1;
}
}
{
for (i=1; i<=NF; i++) {
split($i,b,"=");
if (b[1] in f){
printf("%s ", $i);
}
}
printf("\n");
}
你可以做到:
awk -v filter="srcip,srcintf" -f filter.awk /var/log/syslog
在您指定的过滤器中,以逗号分隔的关键字。它必须找到
注意:此脚本还假设文件的格式为:key1=value key2=value
并且值中没有 space。
$ cat tst.awk
{
delete f
for (i=5; i<=NF; i++) {
split($i,tmp,/=/)
f[tmp[1]] = $i
}
print f["date"], f["time"], f["devname"], f["action"], f["policyid"], f["srcintf"], \
f["dstintf"], f["srcip"], f["srcport"], "----->", f["dstip"], f["dstport"]
}
.
$ awk -f tst.awk file
date=2020-07-21 time=13:13:34 devname="devicename" action="deny" policyid=0 srcintf="someinterface" dstintf="anotherinterface" srcip=1.2.3.4 srcport=57324 -----> dstip=5.6.7.8 dstport=80
以上假定您引用的字符串不包含示例输入中所示的空格。