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

4
  • 2
    Out of interest - why are you fixed on awk?
    – Sobrique
    Jan 12, 2018 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, 2018 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.
    – Adesso
    Jan 12, 2018 at 19:43
  • @Sobrique just trying to improving my skill in the Linux basics, awk and sed has been due for some time now ;)
    – Adesso
    Jan 12, 2018 at 20:50

2 Answers 2

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
5
  • Changing your logic SRC=[^[:space:]]+ to SRC=.{7,15}[[:space:]]+ almost works...
    – Adesso
    Jan 12, 2018 at 20:40
  • adding { if(length($1)) print $1 } to the print logic, solves the problem, but it's not sexy :(
    – Adesso
    Jan 12, 2018 at 20:46
  • @WillemP.Botha, this SRC=.{7,15}[[:space:]]+ is wrong, cause .(dot) matches ANY character including whitespace(s) Jan 12, 2018 at 21:43
  • @WillemP.Botha, if your files may contain records without SRC=... field - use my update, it'll work fine Jan 12, 2018 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, 2018 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
1
  • optimization hint: if ($i ~ /^SRC=/) { print $i; break } Jan 13, 2018 at 5:56

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .