Description
We want to replace each of the last 3 matches of word with six dashes.
Raw Input Desired Output
word_1 word_2 word_3
much more data...
word_4 word_5
much more data...
word_6 word_7
word_8
much more data...
word_9 final word_10
word_1 word_2 word_3
much more data...
word_4 word_5
much more data...
word_6 word_7
------_8
much more data...
------_9 final ------_10
Script and Comments
Script1
[ 1] /word/!b
[ 2] :0
[ 3] $!{
[ 4] N
[ 5] /(.*word){3}/!b 0
[ 6] }
[ 7] :1
[ 8] /\n(.*word){3}/{
[ 9] P
[10] s/^[^\n]*\n//
[11] }
[12] $!{
[13] N
[14] b 1
[15] }
[16] :2
[17] s/^(.*)word/\1------/
[18] x
[19] s/^/\n/
[20] /^\n{3}$/!{
[21] x
[22] /word/b 2
[23] }
[24] x
Comments
  1. The `-r' option of GNU sed must be used to interpret REs as EREs.
  2. The Pattern and the Hold Space are abbreviated to PS and HS, respectively.
  3. Each line before and not including the first one containing the first word is printed by Step [1] and then the next cycle is started.
  4. After reading the line containing the first word, to locate the last 3 matches of word, the following approach is used:
    • The loop consisting of Steps [2] thru [6] keep reading lines and appending them to PS until there are 3 matches of word in PS.
    • Then, if there are 3 matches of word from the second line till the end of PS, we can print then delete the first line of PS since that line does not containing any of the last 3 occurences of word. This is done by Steps [7] thru [10].
    • Otherwise, Steps [12] thru [15] read and append the next line to PS, then sed jumps back to Step [7].
    • When the last line of the file is read, we are sure that PS contains the last 3 matches of word, but there may be more. Therefore, we can not use s/word/------/g. Instead, a loop and a counter is required.
    • Step [17] replaces the last word in PS, and each time a word has been replaced, we add a newline character to HS which is used as a counter.
    • For files containing less than 3 matches of word, the counter will never get 3 newlines. The RE check used in Step [22] is used to prevent from looping infinitely.