1

I have an output which looks like this:

A
A
A

B

A
A
A

C

A
...

I would like to filter the lines surrounded by empty lines.
In this example it would be B and C and so on.

  • There are no three consecutive empty lines – raddirad Apr 18 '17 at 16:34
3

awk reads the input as "paragraphs", or records separated by empty lines if RS is set to the empty string (GNU awk). (setting RS to \n\n+ is similar, but not exactly.) You could then print all records that don't contain a newline:

$ awk -vRS= '$0 !~ /\n/' file1
B
C

That would print the first and last lines too, if they are followed or preceded by an empty line respectively, in effect treating the beginning and end of the file as "empty lines". If you want actual empty lines, something like this would do:

awk 'BEGIN {lines=2} /^$/ {if (lines == 1) print prev; lines=0 } 
     !/^$/ {lines += 1}  {prev=$0}' file1
|improve this answer|||||
1

Try:

awk -v RS= '!/\n/'

That reports the paragraphs that have only one line.

Technically, if the file contained:

A

B
C

D

E

That would also report A and E even though they're not preceded (respectively followed) by an empty line.

If you only wanted D above, you could do:

awk '
  {
    if ($0 != "") {
      ok = wasempty
      wasempty = 0
    } else {
      if (ok) print last
      ok = 0
      wasempty = 1
    }
  }
  ok {last = $0}'
|improve this answer|||||
1

If first/last lines are ruled out because they cannot have empty lines on both sides:

$ cat ip.txt 
A0

B1

A2

A
A

C3

AN
$ awk 'NR>=3 && p2~/^$/ && p1~/./ && /^$/{print p1} {p2=p1; p1=$0}' ip.txt 
B1
A2
C3
  • NR>=3 need at least 3 lines to match condition
  • {p2=p1; p1=$0} saving last line in p1 and last to last line in p2
  • p2~/^$/ && p1~/./ && /^$/ matching given condition, assumes empty line matching should not have white-spaces also and line to match is NOT empty
|improve this answer|||||
0
perl -l -0777ne 'print for /(?:^|\n)\n\K.+(?=\n\n)/g' yourfile

Explanation:

We slurp the file and then the whole file is a single record. In that single record we zoom in on islands which are preceded by 2 consecutive line beginnings and followed by 2 newlines. All such islands are printed by the for loop.


sed -e '
   /./d      # skip a nonempty line
   $!N       # grab the line following an empty line
   /^\n$/D   # if we have 2 consecutive empties, clip the former, n branch to top
   $!N       # we now have ^\nLine\n...
   /\n$/!D   # clip if the seq ^\nLine\n$ not found
   s/.//     # found it! ^\nLine\n$
   P;D       # 
' yourfile
|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.