-1

On a Linux machine with GNU tools I have an ascii file that consists of only 2-line and 3-line paragraphs, each paragraph separated by a newline. All 2-line paragraphs are to be deleted so that all 3-line paragraphs remain separated by a newline. I've been experimenting unsuccessfully with awk paragraphs. Original content:

aaa aaaaaa
bb bbb 
cc cccc ccccc cccc

ddd d
e eeeeee ee

fff ff
ggg gggg gggg
hhh hhh hh hhhh

ii
jjjj jjjj jjjjjj j jjj

The above should look like this:

aaa aaaaaa
bb bbb 
cc cccc ccccc cccc

fff ff
ggg gggg gggg
hhh hhh hh hhhh

I would prefer sed, awk, or perl for this.

3
  • 2
    please update the question with the code you've tried and the (wrong) results generated by said code
    – markp-fuso
    Commented Jul 15 at 20:19
  • Google awk paragraph mode as a starting point.
    – Ed Morton
    Commented Jul 15 at 20:49
  • I've been experimenting with awk -v R strings and the use of the newlines as delimiters. I hope to learn more about that.
    – stampeder
    Commented Jul 15 at 21:18

3 Answers 3

1

With GNU awk:

awk 'BEGIN{FS=RS; RS=""} NF==3{print; print ""}' file

Output:

aaa aaaaaa
bb bbb 
cc cccc ccccc cccc

fff ff
ggg gggg gggg
hhh hhh hh hhhh

Output contains one trailing empty line.

See: 8 Powerful Awk Built-in Variables – FS, OFS, RS, ORS, NR, NF, FILENAME, FNR

2
  • 1
    You should use ORS rather than the extra prints, especially with that link. And you can set the variables on the command line: gawk -vRS='\n\n' -vORS='\n\n' -vFS='\n' 'NF == 3' test.in or gawk 'NF == 3' FS="\n" RS="\n\n" ORS="\n\n" file.
    – Kevin
    Commented Jul 16 at 3:03
  • @Kevin: See my comment to a deleted answer.
    – Cyrus
    Commented Jul 17 at 17:40
0

Using any awk with a blank line at the end of the output:

$ awk -v RS= -F'\n' -v ORS='\n\n' 'NF != 2' file
aaa aaaaaa
bb bbb
cc cccc ccccc cccc

fff ff
ggg gggg gggg
hhh hhh hh hhhh

Using any awk without a blank line at the end of the output:

$ awk -v RS= -F'\n' 'NF != 2{print sep $0; sep=ORS}' file
aaa aaaaaa
bb bbb
cc cccc ccccc cccc

fff ff
ggg gggg gggg
hhh hhh hh hhhh
4
  • We probably want NF != 2. The requirements are badly stated. We are to delete all the 2 line paragraphs, which is clear. But then keep the three line ones, which seems like it should be "keep all other paragraphs, but I believe they are all three-lines".
    – Kaz
    Commented Jul 16 at 17:20
  • @Kaz on re-reading the question I think you're probably right but I'll leave it as-is for now to see what the OP says about it. There's a good chance the OPs whole input is either 2 or 3 lines in which case either condition will work for them.
    – Ed Morton
    Commented Jul 16 at 18:07
  • Confirming that using NF != 2 in that string seems to be the best awk option for my requirements.
    – stampeder
    Commented Jul 16 at 23:08
  • OK, I changed the condition from NF == 3 to NF != 2.
    – Ed Morton
    Commented Jul 17 at 10:18
-1

You can use perl for this (along with several other possibilities)

perl -n -00 -e 'chomp; print "$_\n\n" unless y/\n// == 1' datafile

Or expanded out somewhat,

perl -n -00 -e '
    # -n -00 = while { } loop reading a paragraph at a time
    # -e = execute the following code in the loop
    chomp;                                # Discard trailing newline (if any)
    print "$_\n\n" unless y/\n// == 1;    # Output paragraphs unless they have just 1 newline
' datafile

Result from your example data:

aaa aaaaaa
bb bbb
cc cccc ccccc cccc

fff ff
ggg gggg gggg
hhh hhh hh hhhh
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .