Sed: returns the last match of entries before the end of the file

Using sed, how do I return the last match of a match to the end of the file? (FYI it was simplified)

So far I have tried:

sed -n '/ Statistics |/,$p' logfile.log 

Returns all rows from the first match (almost the entire file)

I also tried:

 $linenum=`tail -400 logfile.log | grep -n " Statistics |" | tail -1 | cut -d: -f1` sed "$linenum,\$!d" logfile.log 

This works, but it wonโ€™t work on the ssh connection in one command, it really needs to be in the same pipeline.

The format of the log file is as follows:

(Statistics logs with subdata are written to each log, the purpose of this command is to return the latest Statistics header along with any associated errors that occur after the header)

 Statistics | Stuff More Stuff Even more Stuff Statistics | Stuff More Stuff Error: incorrect value Statistics | Stuff More Stuff Even more Stuff Statistics | Stuff Error: error type one Error: error type two 

Eof

Refund must be:

 Statistics | Stuff Error: error type one Error: error type two 
+7
source share
6 answers

If you have tac available:

 tac INPUTFILE | sed '/^Statistics |/q' | tac 
+12
source

Your example script has a space before the statistics, but your example data is not displayed. This has a regex that assumes statistics are at the beginning of a line; if this is not true.

 sed -n '/^Statistics |/h;/^Statistics |/!H;$!b;x;p' 

When you see "Statistics", replace the hold space with the current row ( h ). Otherwise add to the hold space ( h ). If we are not at the end of the file, stop here ( b ). Print a hold space at the end of the file ( x extract the contents of the hold space, p print).

In a sed script, commands do not necessarily have a prefix at "address". This is most often a regular expression, but it can also be a line number. The address /^Statistics |/ selects all lines matching the regular expression; /^Statistics |/! selects strings that do not match the regular expression; and $! matches all lines except the last line in the file. For all input lines, commands are executed without an explicit address.

Edit Explain the script in more detail and add the following.

Note that if you need to transfer this to a remote host using ssh , you will need additional citation levels. One possible workaround for a solution, if it gets too complicated, is to save this script to a remote host and just ssh remotehost path/to/script . Another possible workaround is to change the addressing expressions so that they do not contain exclamation points (this is problematic on the command line, for example, in Bash).

 sed -n '/^Statistics |/{h;b};H;${x;p}' 

This is a bit easier!

The third possible workaround, if your stdin ssh pipeline is not tied to other things, should connect to the script from your local host.

 echo '/^Statistics |/h;/^Statistics |/!H;$!b;x;p' | ssh remotehost sed -n -f - file 
+14
source

This might work for you:

 sed '/Statistics/h;//!H;$!d;x' file Statistics | Stuff Error: error type one Error: error type two 
+3
source

If you are happy with awk solution, this view works (besides getting an extra blank line):

 awk '/^Statistics/ { buf = "" } { buf = buf "\n" $0 } END { print buf }' input.txt 
+2
source
 sed ':a;N;$!ba;s/.*Statistics/Statistics/g' INPUTFILE 

should work (GNU sed 4.2.1).

It reads the entire file in one line, then replaces everything from the beginning to the last Statistics (including the word) with Statistics and prints the rest.

NTN

+1
source

It may also work, a slightly simpler version of sed solution given by others above:

 sed -n 'H; /^Statistics |/h; ${g;p;}' logfile.log 

Output:

 Statistics | Stuff Error: error type one Error: error type two 
+1
source

All Articles