5

I am trying to make a script to summarize a file containing below logs in short format.

Snippet of log :

$ cat input.txt
ffffff     1301 2012-08-29T03:13:33 clr         crit
Some serious problem
cccc                            dddddd        eeeeee
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Some serious problem in system.

ffffff     1302 2012-08-29T03:13:33 set         min
Some serious problem
cccc                            dddddd        eeeeee
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Some minor problem in system. 

Desired output:

2012-08-29T03:13:33 clr crit Some serious problem in system.
2012-08-29T03:13:33 set min Some minor problem in system. 

I tried below approch :

$ cat input.txt | grep -iE "set|upd|clr" | awk '{print $3,$4,$5}' >file1
12-08-29T03:13:33  clr crit
12-08-29T03:13:33  set min

Below command gives me 5th line from the pattern "T" ,but the problem is with desired text line, In some cases it is in 5th line and in some cases it is in 4th line.

$ awk '/T/ { show[NR+4]++  } show[NR]' input.txt >file2

$ paste file1 file2 

Query:

In some cases it is in 5th line and in some cases it is in 4th line. How can I make sure to find the exact text. Please let me know if its possible.

Mandar Pande
  • 12,250
  • 16
  • 45
  • 72

3 Answers3

3

The correct way to solve this is just to set awks Record Separator to the null string so that awk knows your input records are separated by blank lines:

$ awk -v RS= -F'\n' '{split($1,a,/ +/); print a[3],a[4],a[5],$NF}' file
2012-08-29T03:13:33 clr crit Some serious problem in system.
2012-08-29T03:13:33 set min Some minor problem in system.

That way if/when you want to print other sections of the record in future or print a count of the number of records or only print unique records based on some key fields or whatever, it's absolutely trivial since awk KNOWS about and is operating on the records.

Ed Morton
  • 188,023
  • 17
  • 78
  • 185
1

It's seem you have a fixed record size of 7 lines so you could do the following with awk:

$ awk 'NR%7==1{printf "%s %s %s ",$3,$4,$5}NR%7==6' file
2012-08-29T03:13:33 clr crit Some serious problem in system.
2012-08-29T03:13:33 set min Some minor problem in system.

This uses the modulus operator to print the third, fourth and fifth field on the first line in the record and the print the whole sixth line.

Chris Seymour
  • 83,387
  • 30
  • 160
  • 202
1

This awk one-line should be more robust:

awk '$3 ~ /[0-9]+-[0-9]+-/{printf "%s%s%s%s%s", $3, OFS, $4, OFS, $5; 
     for(i=0; i<5; i++) getline; print OFS $0}' input.txt

2012-08-29T03:13:33 clr crit Some serious problem in system.
2012-08-29T03:13:33 set min Some minor problem in system.

UPDATE:: Solution without getline:

awk '$3 ~ /[0-9]+-[0-9]+-/{s=NR; printf "%s%s%s%s%s", $3, OFS, $4, OFS, $5}
     NR==s+5{print OFS $0}' input.txt
anubhava
  • 761,203
  • 64
  • 569
  • 643