2

I am a little new to awk, so this question might have been asked, but I can't find a solution to my Question.

Using awk, I would like to search for a string in syslog, and only print the value until the next word boundary.

Rules:

  • Only awk can be used
  • Should be a one line Command in Linux

Test Data: Syslog contains entries made by the Firewall when packets are dropped. These lines of information contains multiple values and vary in length (forget NF). The source IP always start with SRC=

What I have so far:

awk '/SRC=/ { print $13 }' /var/log/syslog*

The problem however is that Field 13 is not always the SRC value.

The rest of the solution can be seen in this Question: Listing a Summary with limits

  • 2
    Out of interest - why are you fixed on awk? – Sobrique Jan 12 '18 at 15:05
  • 1
    Do you really mean "word boundary" or do you want to print until the end of the field (until the next whitespace in awk, by default, or whatever you have set IFS to)? Please edit your question and show us an actual example of your input data and your desired output. – terdon Jan 12 '18 at 15:12
  • nice link for word boundary ;) Yes, that is what I meant. The Target text is in format SRC=192.168.1.1, no spaces, and the default in awk is too use spaces as the IFS. To see a example look at the linked Question please. – Willem P. Botha Jan 12 '18 at 19:43
  • @Sobrique just trying to improving my skill in the Linux basics, awk and sed has been due for some time now ;) – Willem P. Botha Jan 12 '18 at 20:50
4

GNU awk solution:

awk -v FPAT='SRC=[^[:space:]]+' 'NF{ print $1 }' /var/log/syslog*

This will narrow processing records to only one field matching the pattern SRC=[^[:space:]]+


Time performance check (testlog has 22756 lines):

$ time(awk -v FPAT='SRC=[^[:space:]]+' 'NF{ print $1 }' testlog > /dev/null)

real    0m0.186s
user    0m0.164s
sys 0m0.000s

$ time(awk '{for(i=1;i<=NF;i++) {if ($i ~ /^SRC=/) print $i}}' testlog > /dev/null)

real    0m0.282s
user    0m0.256s
sys 0m0.000s
  • Changing your logic SRC=[^[:space:]]+ to SRC=.{7,15}[[:space:]]+ almost works... – Willem P. Botha Jan 12 '18 at 20:40
  • adding { if(length($1)) print $1 } to the print logic, solves the problem, but it's not sexy :( – Willem P. Botha Jan 12 '18 at 20:46
  • @WillemP.Botha, this SRC=.{7,15}[[:space:]]+ is wrong, cause .(dot) matches ANY character including whitespace(s) – RomanPerekhrest Jan 12 '18 at 21:43
  • @WillemP.Botha, if your files may contain records without SRC=... field - use my update, it'll work fine – RomanPerekhrest Jan 12 '18 at 21:44
  • 2
    +1. BTW, GNU awk understands the PCRE \S shorthand for [^[:space:]] so this could be written as awk -v FPAT='SRC=\\S+' 'NF{ print $1 }' (note the double-backslash in the FPAT - it's required here). Also, -v FPAT='SRC=[0-9.]+' works. – cas Jan 13 '18 at 4:21
3

KISS solution (should work in any awk flavor) - simply loop over the fields and test one-by-one:

awk '{for(i=1;i<=NF;i++) {if ($i ~ /^SRC=/) print $i}}' /var/log/syslog
  • optimization hint: if ($i ~ /^SRC=/) { print $i; break } – RomanPerekhrest Jan 13 '18 at 5:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.