Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have a file containing text in paragraphs (lines with text separated by one or more empty lines). I would like to reverse the order of paragraphs (i.e. last paragraph will become the first, ...), preferably by using sed.

I am looking for a sed command which would do to a file of paragraphs, what tac would do to a files of lines.

share|improve this question
add comment

4 Answers

up vote 5 down vote accepted

Using sed isn't quite as straight-forward as mentioned by Joseph R.. However, you could say:

sed '/./{H;d;};x;s/\n/={NL}=/g' inputfile | \
sed -e 's/^={NL}=//' -e '1!G;h;$!d' | \
sed G | sed 's/={NL}=/\'$'\n/g'

Given a sample input:

Para 1 line 1
Para 1 line 2
Para 1 line 3

Para 2 line 1
Para 2 line 2
Para 2 line 3

Para 3 line 1
Para 3 line 2
Para 3 line 3

this would produce:

Para 3 line 1
Para 3 line 2
Para 3 line 3

Para 2 line 1
Para 2 line 2
Para 2 line 3

Para 1 line 1
Para 1 line 2
Para 1 line 3

It's worth mentioning that this solution (as well as the alternate Perl one) require a blank line at the end of the input file in order to work as expected.

share|improve this answer
add comment

This solution uses both tac and perl to read a paragraph at a time. It does not require reading the whole file into memory.

tac file | perl -00 -lpe '$_ = join "\n", reverse split /\n/'

Reverse all the lines of the file, then for each reversed paragraph, reverse the lines.

share|improve this answer
    
This looks very elegant and efficient. However, this solution also condenses multiple empty (i.e separating) lines into one –  Martin Vegter Feb 16 at 14:08
add comment

There might be a way to do this with sed, but I doubt it will be simple. Here's how I would do it in Perl:

perl -n00e 'push @paragraphs,$_; END{print for reverse @paragraphs}' your_file

This works because defining the input record separator as the null character (-00) tells Perl to operate in paragraph mode. Perl's definition of a paragraph1 matches your definition exactly.


1Look under the heading Other values for $/

share|improve this answer
    
this works indeed. The only small problem is, it does not preserve multiple empty lines separating the paragraphs. Instead, all paragraphs are separated by exactly one empty line. –  Martin Vegter Feb 16 at 13:41
add comment
gem install facets

ruby -r facets/string \
     -e 'puts $stdin.read.strip.shatter(/\n\n+/).reverse.join("")' < file

This should preserve your paragraph spacing (while being more readable than sed :) ) Although, props to devnull for an awesome answer.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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