2

I have the following contents in my file file.txt

Start
1
2
3
5
end
Start
a
b
c
d
end

How do i use only awk to get the section which is at the end from "start" to "end" as follows?

Start
a
b
c
d
end

Tried efforts:

awk '/Start/ {{ f = 1;n++ }} f && n == 2; /end/ {{ f = 0 }}' file.txt
RavinderSingh13
  • 130,504
  • 14
  • 57
  • 93
Sandeep
  • 23
  • 3
  • if you already know how to get first match, here's a tip to get the last match: use `tac` to reverse input file linewise, adjust your code to get first match, then use `tac` again – Sundeep Sep 30 '20 at 14:24
  • 1
    i tried the following command awk '/Start/ {{ f = 1;n++ }} f && n == 2; /end/ {{ f = 0 }}' file.txt – Sandeep Sep 30 '20 at 14:32
  • 1
    But i dont want to give any number "2" since i may not know how many occurrences happens. – Sandeep Sep 30 '20 at 14:33
  • @Sandeep, Thank you for posting your efforts, kindly do add them in your question since comments are NOT meant for showing efforts, keep it up, cheers. – RavinderSingh13 Sep 30 '20 at 14:43
  • 2
    What if you had a `start` line after the last `end` line in the input? Should from the last `start` to end-of-file be printed or the block of text between the 2nd-last `start` and the last `end`? – Ed Morton Sep 30 '20 at 16:42

2 Answers2

4

You may use this awk:

awk '$1 == "Start" { s = ""; p = 1 }
p { s = s $0 ORS }
$1 == "end" { p = 0 }
END { printf "%s", s }' file
Start
a
b
c
d
end
anubhava
  • 761,203
  • 64
  • 569
  • 643
4

With tac + awk solution, could you please try following.

tac Input_file | awk '/^end/{found=1} found; /^Start/{exit}' | tac

Explanation: tac will print Input_file in reverse order(from bottom to up manner), then passing its output to awk command and in awk code printing from first occurrence of end to till first occurrence of start. Exiting from awk code when first occurrence of start is found, again this output is being send to tac which will reverse the output and post it in original form of Input_file.


2nd solution: Using GNU awk one could try like but it assumes that there is NO discrepancy(means after each start there is end keyword present in OP's Input_file else it will give false positive results) in start and end keywords appearance.

awk -v RS= '{sub(/.*Start/,"Start")} 1' Input_file
RavinderSingh13
  • 130,504
  • 14
  • 57
  • 93