0

I have a file, file.txt, like this:

start cal
end cal
start eff
end eff
start cal
error
end cal
start dod
end dod

What I want to get is the line between the last set of 'start cal' and 'end cal'. I am using tac and grep to do it. But in vain. Any help please? Below is my code:

tac file.txt | grep -m1 'start cal*end cal'

What am I doing wrong? For the example above, I need the command to return 'error'.

3 Answers 3

1

Grep is not good tool for this task. It does line based matching. You can consider using awk.

if you have single line in between:

tac file|awk '/end cal/{p=1;next}/start cal/{exit}p'

If it could be multiple lines:

tac file|awk '/end cal/{p=1;next}/start cal/{exit}p'|tac

It outputs:

error
Sign up to request clarification or add additional context in comments.

3 Comments

Beat me by 13 seconds! What's that /pattern/ { commands } variable syntax? I don't recognize it.
I don't understand your question. sorry.. :-( @nephtes
Oh, never mind, I misread. It's a condition for the default rule. Avoids the "if (echo) print" in my solution.
1

I don't know if grep can do it, but here it is in gawk. I'll be the first to admit, it's not exactly pretty.

tac file.txt | gawk '/start cal/ { exit } { if (echo) print } /end cal/ { echo = 1 }'

n.b. Kent's answer is better polished.

Comments

0

You're doing two things wrong:

  1. grep examines each line separately, so a pattern can never match across two or more lines
  2. the regex start cal*end cal matches start ca, followed by 0 or more ls, followed by end cal

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.