2

I have a log file with text:

Jan 10 09:56:17  1484207777.225918 GET "8.8.8.8" "curl/7.27.0" #0121484207777.226639 GET "8.8.8.9" "curl/7.21.0" #0121484207777.226639 GET "8.8.5.9" "curl/7.22.0"
Jan 10 19:59:17  1484207777.225456 GET "8.8.6.8" "curl/7.24.0" #0121484207777.226639 GET "8.8.5.9" "curl/7.21.0" #0121484207777.226425 GET "8.8.5.9" "curl/7.22.0"

I need replace symbols "#" to line break (\n) and add date/time from this line.

I need result:

Jan 10 09:56:17  1484207777.225918 GET "8.8.8.8" "curl/7.27.0" 
Jan 10 09:56:17  0121484207777.226639 GET "8.8.8.9" "curl/7.21.0" 
Jan 10 09:56:17  0121484207777.226639 GET "8.8.5.9" "curl/7.22.0"
Jan 10 19:59:17  1484207777.225456 GET "8.8.6.8" "curl/7.24.0" 
Jan 10 19:59:17  0121484207777.226639 GET "8.8.5.9" "curl/7.21.0" 
Jan 10 19:59:17  0121484207777.226425 GET "8.8.5.9" "curl/7.22.0"

I tried with sed, but without result.

for a in $(cat logs)

do

b=$(cat logs | awk '{print $1, $2, $3}')

echo "$a" | sed 's/#/\n"$b"/g'

done

Can you help me please with this task?

  • What are the delimiters? are there tabs after the date field, or is everything space-delimited? – steeldriver Jan 12 '17 at 15:02
  • delimiters between lines in log file - line translation (\n). Yes, everywhere separated by a space. – Oleksii Jan 12 '17 at 15:09
  • awk -F ' +' '{n = split($2,a,"#"); for (i=1;i<=n;i++) print $1,a[i]}' logs worked if I have in logs file two space between date and text, but I have only one=( – Oleksii Jan 12 '17 at 16:03
4

If your date field is followed by multiple spaces while the other fields are separated by single spaces as shown in your example, then you could do

$ awk -F'  +' '{n = split($2,a,"#"); for (i=1;i<=n;i++) print $1,a[i]}' log
Jan 10 09:56:17 1484207777.225918 GET "8.8.8.8" "curl/7.27.0"
Jan 10 09:56:17 0121484207777.226639 GET "8.8.8.9" "curl/7.21.0"
Jan 10 09:56:17 0121484207777.226639 GET "8.8.5.9" "curl/7.22.0"
Jan 10 19:59:17 1484207777.225456 GET "8.8.6.8" "curl/7.24.0"
Jan 10 19:59:17 0121484207777.226639 GET "8.8.5.9" "curl/7.21.0"
Jan 10 19:59:17 0121484207777.226425 GET "8.8.5.9" "curl/7.22.0"

More generally, you could substitute the # as follows

$ awk '{gsub(/#/, sprintf("\n%s %s %s ", $1, $2, $3))} 1' log
Jan 10 09:56:17  1484207777.225918 GET "8.8.8.8" "curl/7.27.0"
Jan 10 09:56:17 0121484207777.226639 GET "8.8.8.9" "curl/7.21.0"
Jan 10 09:56:17 0121484207777.226639 GET "8.8.5.9" "curl/7.22.0"
Jan 10 19:59:17  1484207777.225456 GET "8.8.6.8" "curl/7.24.0"
Jan 10 19:59:17 0121484207777.226639 GET "8.8.5.9" "curl/7.21.0"
Jan 10 19:59:17 0121484207777.226425 GET "8.8.5.9" "curl/7.22.0"
  • steeldriver, sorry, in log file between data and text only one space. In this case you command not work=( – Oleksii Jan 12 '17 at 15:48
0

A small python script can do the job:

#!/usr/bin/env python
from __future__ import print_function
import sys

for line in sys.stdin:
    timestamp = "\n" + " ".join(line.strip().split()[0:3])
    print(line.replace('#',timestamp),end="")

And demo of how it works:

$ ./break_lines.py < input.txt                                                                                           
Jan 10 09:56:17  1484207777.225918 GET "8.8.8.8" "curl/7.27.0" 
Jan 10 09:56:170121484207777.226639 GET "8.8.8.9" "curl/7.21.0" 
Jan 10 09:56:170121484207777.226639 GET "8.8.5.9" "curl/7.22.0"
Jan 10 19:59:17  1484207777.225456 GET "8.8.6.8" "curl/7.24.0" 
Jan 10 19:59:170121484207777.226639 GET "8.8.5.9" "curl/7.21.0" 
Jan 10 19:59:170121484207777.226425 GET "8.8.5.9" "curl/7.22.0"

Explanation of how it works is simple - we break line into words, and take first 3 words and join them together into a string which has newline attached in front of it after that we simply replace # with that new string - and viola !

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.