11

Example file:

Pattern 1

AAAAAAAAAA
BBBBBBBBBB

Pattern 2

I want to print the lines between two patterns in a file in one line. From a previous question How to print lines between two patterns, inclusive or exclusive (in sed, AWK or Perl)? I found the very nice

awk '/Pattern 1/{flag=1; next} /Pattern 2/{flag=0} flag' file

With output:

AAAAAAAAAA
BBBBBBBBBB

My desired output:

AAAAAAAAAABBBBBBBBBB
  • 3
    What should happen if `Pattern1` exists but `Pattern2` doesn't or vice-versa? What if both were on 1 line the expected order? What if they were both on 1 line in the reverse order? What if you had a blank line in the middle of the text between the 2 delimiters? – Ed Morton Mar 22 '21 at 12:35
  • 1
    Can there be multiple occurrences of `Pattern 1 ... Pattern 2` in the input and, if so, do you want all of their contents printed or just the first or just the last or something else? – Ed Morton Mar 22 '21 at 13:05
  • In my (lucky) case the patterns are always consistent. – Mike de Groot Mar 24 '21 at 16:24
  • @anubhava How do I do this – Mike de Groot Mar 28 '21 at 16:57

5 Answers5

9

Have your awk program in this way, written and tested in GNU awk.

awk '
/Pattern 2/{
  if(found){
    print val
  }
  found=""
  next
}
/Pattern 1/{
  found=1
  next
}
found{
  val=val $0
}
'   Input_file

Explanation: Adding detailed explanation for above.

awk '                      ##Starting awk program from here.
/Pattern 2/{               ##Checking if Pattern 2 is found here then do following.
  if(found){               ##Checking if found is set then do following.
    print val              ##Printing val here.
  }
  found=""                 ##Nullifying found here.
  next                     ##next will skip all statements from here.
}
/Pattern 1/{               ##Checking if Pattern 1 is found in current line.
  found=1                  ##Setting found to 1 here.
  next                     ##next will skip all statements from here.
}
found{                     ##Checking condition if found is SET then do following.
  val=val $0               ##Creating val variable here which is keep adding current line values in it.
}
'  Input_file              ##Mentioning Input_file name here. 
RavinderSingh13
  • 130,504
  • 14
  • 57
  • 93
9

You may use this awk:

awk '/Pattern 2/ {if (s!="") print s; s=f=""} f {s = s $0} /Pattern 1/ {f=1}' file

AAAAAAAAAABBBBBBBBBB
anubhava
  • 761,203
  • 64
  • 569
  • 643
  • In the case of `Pattern 1 foo Pattern 1 bar Pattern 2` that would print `foobar` while [my answer](https://stackoverflow.com/a/66746370/1745001) would print `bar`. idk which is correct, just mentioning the difference as the provided example doesn't cover that case. – Ed Morton Mar 22 '21 at 14:21
  • yes that's a very good point, not sure which one OP wants – anubhava Mar 22 '21 at 14:27
5

And also with awk:

awk -v RS= '!/Pattern/ {sub(/\n/,"");print}' file
AAAAAAAAAABBBBBBBBBB
Carlos Pascual
  • 1,106
  • 1
  • 5
  • 8
  • I don't think you can assume that `Pattern 1` and `Pattern 2` share a common substring `Pattern`, I think those terms are just [bad] examples the OP used, nor that they don't occur elsewhere in the text, nor that they're always in the order required for printing (e.g. `Pattern 2... Pattern 1`). – Ed Morton Mar 22 '21 at 12:53
  • Ok. Now I see how the word `pattern` can be ambiguous. – Carlos Pascual Mar 24 '21 at 17:11
4

With GNU awk for multi-char RS and assuming your "Pattern"s really to take up whole lines and can't occur elsewhere in your input (easy fix if that's wrong):

$ awk -v RS='Pattern 2' 'sub(/.*Pattern 1/,""){gsub(/\n/,""); print}' file
AAAAAAAAAABBBBBBBBBB

or with any awk:

awk 'f{ if (/Pattern 2/){print buf; f=0} else buf=buf $0 } /Pattern 1/{f=1; buf=""}' file
AAAAAAAAAABBBBBBBBBB
Ed Morton
  • 188,023
  • 17
  • 78
  • 185
3

You can set the output record separator to an empty string by using -v ORS=:

awk -v ORS= '/Pattern 1/{flag=1; next} /Pattern 2/{flag=0} flag' file

See an online demo.

To print a newline at the end, add END{print "\n"}:

 awk -v ORS= '/Pattern 1/{flag=1; next} /Pattern 2/{flag=0} flag; END{print "\n"}' file > newfile

See the Ubuntu 18 screenshot:

enter image description here

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563