2

I have to extract the exception and corresponding stack trace starting from a line number in a log file. I know the starting line no of the error. how can i find out where the stack trace will end from the below example? Appreciate your help

example
-------
2016-10-07 15:49:07,537 ERROR Some exception
 stacktrace line 1
 stacktrace line 2
 .
 .
 stacktrace line n
2016-10-07 15:49:07,539 debug blah blah blah
2016-10-07 15:49:07,540 debug blah blah blah

3 Answers 3

0

To summarize, you want to print lines starting with the line number that you specify and continuing until just before the first following line that starts with a date. In your example, the starting line is 3. In that case:

$ awk '{if (NR==3)f=1; else if (/^[0-9-]{10} /)f=0} f{print}' trace.log
2016-10-07 15:49:07,537 ERROR Some exception
 stacktrace line 1
 stacktrace line 2
 .
 .
 stacktrace line n

The above code works as follows:

  • if (NR==3)f=1

    On the line number you specify, set variable f to one.

  • else if (/^[0-9-]{10} /)f=0

    On other lines, set f to zero if the line starts with 10 characters that are digits or dashes followed by a space. In other words, set f to zero on the first line that starts with something that looks like a date.

    If need be, we can get use more complex regexes to identify the start of a date. For example, the following requires that the line start with something that looks like a data, followed by a space, followed by something that looks like time, followed by a comma.

    awk '{if (NR==3)f=1; else if (/^[0-9-]{10} [0-9:]{8},/)f=0} f{print}' trace.log
    

    Still further improvements on this are possible.

  • f{print}

    If f is nonzero, print the line.

    For brevity, we could replace f{print} with just f. This is possible because, when an action is not specified explicitly, the default action of print is used.

Alternative

Some versions of awk don't support repetition factors like {10}. If that is the case on your system, try:

awk '{if (NR==3)f=1; else if (/^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] /)f=0} f{print}' trace.log
9
  • Not all the stack trace lines are intended by a space. Some of them are having a space and some of them are not.The row after stack trace begins with a date and time so is there any other way I can cut it based on that?
    – Shawn
    Oct 13, 2016 at 20:30
  • @Shawn That is possible. By the way, do you want to print all stacktraces or just the one that starts on your specified line?
    – John1024
    Oct 13, 2016 at 20:33
  • I need the entire stack trace.
    – Shawn
    Oct 13, 2016 at 20:35
  • @Shawn Let me clarify: do you want to print all exceptions+stacktraces in the file or just the one exception+stacktrace that starts on the line number that you specify?
    – John1024
    Oct 13, 2016 at 20:37
  • I need the exception & stack trace that starts from the line number i specify. I do not need the entire exceptions in the file. Sorry if I confused you.
    – Shawn
    Oct 13, 2016 at 20:42
0

Assuming all stack trace lines start with a whitespace (space/tab), you can match them ([[:blank:]]) at the start of the line (^):

grep '^[[:blank:]]' file.log
0

If the trace that you want to extract begins on line 2 of trace.log, and its end is indicated by a line that begins with a date in YYYY-MM-DD format (and there are no such lines with the trace), then

sed -nE '2,/^[0-9]{4}-[0-9]{2}-[0-9]{2} /p' trace.log

will print every line from line 2 through line n+3 (the first line after the trace that begins with a date).  Since you don’t want that last line, pipe the above into a command that removes the last line:

sed -nE '2,/^[0-9]{4}-[0-9]{2}-[0-9]{2} /p' trace.log | head -n -1

or

sed -nE '2,/^[0-9]{4}-[0-9]{2}-[0-9]{2} /p' trace.log | sed '$d'

If you need to search for a date and a time, then search for

^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}

You must log in to answer this question.

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