Ubuntu – Move pattern to beginning of line

grepregexsed

I am trying to reformat a log file such that date and time appear at the beginning of the line. My logs look like this:

blah, blah, blah, Friday, Mar 13,2015 16:59:42
yadi, yadi, yada, Friday, Mar 13,2015 16:51:11

I would like them to look like this:

Friday, Mar 13,2015 16:59:42 blah, blah, blah
Friday, Mar 13,2015 16:51:11 yadi, yadi, yada

I have gone so far as to find the right grep pattern with grep -o -i -e '[a-zA-Z]*, [a-z][a-z][a-z] [0-9]*,[0-9][0-9][0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]' ~/log.txt .

How can I move these pattern results to the left of the information string? Thanks for your help.

Best Answer

Try sed with the following regex:

$ sed -i.bak 's_\(.*\),[[:blank:]]\([[:alpha:]]\+,[[:blank:]][[:alpha:]]\+[[:blank:]][[:digit:]]\+,[^,]\+$\)_\2 \1_' file.txt 
Friday, Mar 13,2015 16:59:42 blah, blah, blah
Friday, Mar 13,2015 16:51:11 yadi, yadi, yada

Here we have used the sed's group substitution method to get the desired output.

  • \(.*\) will match upto blah, blah, blah as we have ,[[:blank:]] to match , after it.
  • \([[:alpha:]]\+,[[:blank:]][[:alpha:]]\+[[:blank:]][[:digit:]]\+,[^,]\+$\) will match the remaining portion of the line (the portion we want to put at the start).

Then we have \2 \1 to put the second group at first and then then a space and then the first group.

The original file will be backed up as file.txt.bak, if you don't want that use just -i instead of -i.bak.

**Although you will get the desired output, using Regex/sed will not be the optimum solution in this case.

EDIT: If you have a line like [Internet disconnected] Friday, Mar 13,2015 15:48:34, try this:

$ sed -i.bak 's_\(.*[^,]\),*[[:blank:]]\([[:alpha:]]\+,[[:blank:]][[:alpha:]]\+[[:blank:]][[:digit:]]\+,[^,]\+$\)_\2 \1_' file.txt 
Friday, Mar 13,2015 15:48:34 [Internet disconnected]
Friday, Mar 13,2015 16:59:42 blah, blah, blah
Friday, Mar 13,2015 16:51:11 yadi, yadi, yada

In the previous regex we had \(.*\),[[:blank:]] (a comma and a whitespace after the first matching group), now to include the new line in the output we have made the first matching group \(.*[^,]\) to ensure that it does not end with a comma and then we have matched ,* i.e. one or more commas. So, the new sed command will work for all mentioned cases.