0

How can I print all data between two matches, staring from specific line after the first match. For example, let's say I have two patterns Linux and Unix and there are entries between these two words I would like to print data from specific line after the word Linux, in the example below line #6 after Linux, until the word Unix:

Linux
12
32
34
556
676
77
85434
rdb
232323
232435656
Unix
98736
4345
4546456
456

expected output:

85434
rdb
232323
232435656

How can I do it using awk, sed and grep?

don_crissti
  • 79,330
  • 30
  • 216
  • 245

4 Answers4

4

Whenever you see relative addressing, you should reach for ed.

echo '/Linux/+7,/Unix/-1p' | ed -s input_file.txt -

Or, as a heredoc:

ed -s input_file.txt - <<\EOF
/Linux/+7,/Unix/-1p
EOF
Rakesh Sharma
  • 755
  • 4
  • 3
2

Try this,

awk '/^Linux$/{flag=1;next}/^Unix$/{flag=0}flag' file | tail -n +7

Or without tail:

awk '/^Linux$/{flag=1;n=NR;next}/^Unix$/{flag=0};flag&&NR>(n+6);' file

Explanation:

  • Search for pattern ^Linux$, and if found, set flag to 1 (true) and move directly to next line.
  • Go on until pattern ^Unix$ was found and set flag to 0 (false)
  • The flag at the end is an awk specific notation. If flag is true, print the line, else do nothing.
  • flag is just a variable name and can be anything, e.g. f or printthisline.

Using Gnu sed:

sed '/^Linux$/,/^Unix$/{//!b};d' file | tail -n +7
pLumo
  • 22,231
  • 2
  • 41
  • 66
2

I would write one of

sed -n '/Linux/,/Unix/p' file | sed '1,7d;$d'
# or
awk '/Linux/ {nr = NR} /Unix/ {exit} nr && NR > nr+6' file
glenn jackman
  • 84,176
  • 15
  • 116
  • 168
  • `sed -e '/Linux/,/Unix/!d;/Linux/{N;N;N;N;N;N;N;s/.*\n//' -e '}' -e '/Unix/d'` so as to avoid pipes and two `sed` invocations though really, `sed` should be avoided anytime one has to count stuff... – don_crissti Sep 28 '18 at 14:35
  • 1
    Yeah, I was fooling around with sed and loops, trying to cram it into a single sed program before I decided it wasn't worth the effort. – glenn jackman Sep 28 '18 at 14:44
0

if you search with grep you can do this:

  • grep -A 5 "string used to search" <path-to-file(s)> will show the 5 lines after the matched string
  • grep -B 5 "string used to search" <path-to-file(s)> will show the 5 lines before the matched string
  • grep -C 5 "string used to search" <path-to-file(s)> will show the 5 lines after and before the matched string (C stands for context)

for your example, it would be: grep -A 2 -B 1 "rdb" <path-to-file(s)>

Kramer
  • 166
  • 6
  • He wants to search key words Linux and Unix, not rdb. Although I think he doesn't know how many lines will lie in between. – pLumo Sep 28 '18 at 11:20
  • given his statement: _How can I print all data between two matches, staring from specific line after the first match._ and his expected output, I wanted to make it simple. I guess your assumption _Although I think he doesn't know how many lines will lie in between._ was correct, but what I provided is not incorrect as per his request, is it? – Kramer Sep 28 '18 at 12:47
  • yes it is incorrect, as OP says "*For example, let's say I have [...]*" which tells me that his text is just an example and not the real text. While your solution works for his example, it might not work for his real text. – pLumo Sep 28 '18 at 13:12
  • Your answer is the moral equivalent of `sed -n '8,11p'` or `printf '85434\nrdb\n232323\n232435656\n'` — they all produce the requested output for the example input in a trivial way, but they don’t solve the problem as described. – G-Man Says 'Reinstate Monica' Dec 30 '19 at 22:45