75

I know that by using the "-A NUM" switch I can print specific number of trailing lines after each match. I am just wondering if it's possible to print trailing lines until a specific word is found after each match. e.g. When I search for "Word A" I want to see the line containing "Word A" and also the lines after it until the one containing "Word D".

context:

Word A
Word B
Word C
Word D
Word E
Word F

command:

grep -A10 'Word A'

I need this output:

Word A
Word B
Word C
Word D
B Faley
  • 4,343
  • 11
  • 39
  • 48

3 Answers3

111

It seems that you want to print lines between 'Word A' and 'Word D' (inclusive). I suggest you to use sed instead of grep. It lets you to edit a range of input stream which starts and ends with patterns you want. You should just tell sed to print all lines in range and no other lines:

sed -n -e '/Word A/,/Word D/ p' file
Teddy
  • 1,555
  • 10
  • 13
saeedn
  • 2,494
  • 3
  • 20
  • 15
  • 1
    Any tips on how to make it exclusive (for any generic situation, not just OP's)? – 2rs2ts Jun 18 '13 at 17:18
  • 7
    @2rs2ts to make it exclusive, just add | sed -e '1d;$d', that is remove first and last line – holroy Jun 26 '15 at 09:54
  • 2
    And if you want to exclude all lines between -- that is, you want to just see lines that are outside the two matches -- then: sed -n -e '/pattern A/,/pattern D/d; p' This says, "delete from pattern A to pattern D and print everything else". Unfortunately, this match is greedy. That means if patterns A and D appear more than once, you're going to match from the first pattern A to the last pattern D. I'm afraid Perl or Python are your friends if that's the case. – fbicknel Dec 19 '18 at 19:07
  • 2
    How to achieve this with a shell variable inside the pattern ? It is not possible to embed a variable inside an awk/sed pattern enclosed by // (cause it treats everything inside as a regex) as this thread and this one confirm. You need another way in order to fetch the value of a shell variable. However this also seems like the only way to print a range of lines between two patterns. Anyone knows of a solution ? – Atralb May 21 '20 at 03:30
  • 1
    @Atralb use double quotes rather than single quotes like sed -n -e "/$pattern1/,/$pattern2/ p" file. see https://askubuntu.com/questions/76808/how-do-i-use-variables-in-a-sed-command – enharmonic Jan 28 '21 at 18:16
25

why not use awk ?

awk '/Word A/,/Word D/' filename
slm
  • 369,824
cesar
  • 577
  • 2
    sed appears to be able to do this much more efficiently if a large number of files are involved. awk may be easier to remember, but sed seems to be worth a sticky note in my brain. – JimNim Nov 24 '14 at 16:02
  • 1
    awk is superior if Word D falls on the same line as Word A, and possibly elsewhere, eg Word A Word D\nWord D with sed will show two lines where as awk will show one. Additionally one can still use variables with awk, eg awk -v _word="Word A" '$0 ~ _word,/Word D/' "/some/file", so sed maybe more efficient but when dealing with searches of two strings that may or may-not fall on the same line, awk definitely be more reliable. – S0AndS0 Oct 26 '18 at 20:50
  • it seems that awk better handles the case that the file contains sequences of A and B and you only want to capture what's between each such sequence. it looks like sed doesn't follow these semantics in my case at least. – matanox Oct 28 '19 at 18:51
  • This works amazing when piping from tail. Eg. tail -5000f log/development.log |awk '/Started.GET.../,/Parameters/' which is useful in Ruby on Rails application logs for getting the lines associated with the top of the request (the original HTTP request through to the parsed parameters). What might improve this is if there is a way to add a separator similar to greps -A2 or -C2 flags. – Peter P. Apr 06 '20 at 21:41
12
perl -lne 'print if /Word A/ .. /Word D/' file

or

cat file | perl -lne 'print if /Word A/ .. /Word D/'
vinian
  • 131
  • 2
    +1 to counter the drive-by downvote. I'd still use sed for this, unless you need the power of Perl regular expressions to select the delimiting lines. – tripleee Jul 02 '13 at 09:32
  • People who wrote sed in the 70s must be thankful :-) – matanox Oct 28 '19 at 18:41