Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm having a program that intermingles data segments into log output:

log message
log message
log messge

I'm looking for something like,


but it should only print the last data segment, and without the surrounding 'tags'.

share|improve this question
If the data lines are complex please expand your example to show one of them. – slm Oct 20 '13 at 3:16
@awkward_grep I'm guessing your choice of user name was influenced by this? :) – Joseph R. Oct 20 '13 at 19:43

With awk, start accumulating data after a start marker and stop when you encounter an end marker. Reinitialize the data accumulator if you encounter a new start marker.

awk '
    /-BEGIN INLINE DATA-/ {data = ""; storing = 1}
    /-END INLINE DATA-/ {storing = 0}
    storing {data = data "\n" $0}
    END {print data}
share|improve this answer

You can pipe two seds like this:

<your program> | tac | sed '1,/END INLINE DATA/d' | sed '/BEGIN INLINE DATA/,$d' | tac
share|improve this answer
but this will only print one line – awkward_grep Oct 20 '13 at 3:07
Sorry, I misread. Just omit the tail at the end and it should pick the first data block. – Karol Oct 20 '13 at 3:20
Duh, you want the last block. Just use tac before and after the seds. – Karol Oct 20 '13 at 3:27
tac log.txt | sed '1,/END INLINE DATA/d' | sed '/BEGIN INLINE DATA/,$d' | tac

seems to do the job

share|improve this answer
I'm guessing this is taken from Karol's answer. If the answer has helped you, the correct way of indicating this is to mark it as accepted (use the tick box below the voting markers next to the question). Please note that Stack Exchange format is different from conventional forums. – Joseph R. Oct 20 '13 at 19:38

You can use this command to get what you want:

$ sed -n '/BEGIN/,/END/p' < data.txt | sed '1d;$d' | tail -1


The sed command prints all the lines (inclusive) between the BEGIN and END lines. The 2nd sed command chops off the first and last lines, while the tail command returns the last line.


You could easily use your awk line as well:

$ awk '/-BEGIN INLINE DATA-/,/-END INLINE DATA-/'  data.txt | sed '1d;$d' | tail -1
share|improve this answer
But the OP doesn't want the last line (s)he wants the last data block. – Joseph R. Oct 20 '13 at 19:38
@JosephR. - yeah that's why I asked him/her to add an example of the "data" segment/line/whatever it is so we could make sure our solutions were apt. – slm Oct 20 '13 at 19:50

Here's a rather unorthodox way of doing it in Perl:

perl -ne '
  BEGIN{ $/="----BEGIN INLINE DATA----\n" } # Set input record separator

  $payload= s/----END INLINE DATA----.*\z//rs; # Remove end marker and messages

  END{ print $payload } # Print the last payload

' file

This needs Perl v5.14 or higher. If you're stuck with an older version of Perl you'll need an extra line:

perl -ne '
  BEGIN{ $/="----BEGIN INLINE DATA----\n" } # Set input record separator

  $payload= $_; # Copy current line into $payload
  $payload=~ s/----END INLINE DATA----.*\z//s; # Remove end marker and messages

  END{ print $payload } # Print the last payload

' file
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.