Я хочу как-то напечатать слова, с которых начинается слово, например 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 $5,$6,$7,$25,$26,$17,$21,$15,$16,"-----> "$19,$20}'

Также не все строки имеют srcip в одном и том же «поле». поэтому некоторые строки действительно искажены.

Или для этой цели будет лучше использовать средство переписывания сообщений системного журнала? как бы ты решил это? заранее спасибо!

0
legogubben 21 Июл 2020 в 14:46

3 ответа

Лучший ответ
$ 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

Выше предполагается, что ваши строки в кавычках не содержат пробелов, как показано в вашем примере ввода.

1
Ed Morton 21 Июл 2020 в 15:06

Если у вас есть 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 и что в значениях нет пробелов.

0
Luuk 21 Июл 2020 в 12:59

Я представляю вам ответ awk, который является гибким и, вместо простого однострочного, немного более программным способом. В вашем лог-файле есть строки, которые в общем выглядят так:

key1=value1 key2=value2 key3=value3 ...

Идея в этом awk состоит в том, чтобы разбить его на массив в awk, который является ассоциативным, так что элементы могут быть вызваны как:

a[key1]=>value1 a[key2]=>value2 ... a[key2,"full"]=>key2=value2 ...

Используя функцию, которая описана в этом ответе, вы можете написать:

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($0," ","=",a) }
    { print a["date","full"],a["time","full"],a["devname","full"],a["action","full"] }
   ' file

Этот метод очень гибкий. Также нет зависимости в порядке строки или чего-либо еще.

Примечание: вышеупомянутый метод не заботится о цитировании. Так что, если внутри строки в кавычках появляется пробел, это может привести к путанице.

0
kvantour 21 Июл 2020 в 12:52