home *** CD-ROM | disk | FTP | other *** search
- From: alfie@cs.warwick.ac.uk (Nick Holloway)
- Newsgroups: alt.sources,comp.lang.perl
- Subject: Perl script to reverse the order of lines.
- Message-ID: <*||&R~@warwick.ac.uk>
- Date: 14 Feb 91 16:49:20 GMT
-
- The included script reversing the order of lines in a file. Unlike
- 'rev' which reverses the characters in each line, 'reverse' will
- reverse the order of the lines. Think of it as reversal in the other
- dimension! The usage is "reverse [ file ... ]"
-
- The script is for you to do with as you please, though I would
- appreciate the credit remaining in the source. I must admit that after
- the original use, I haven't used it since, but you may find it
- useful... one day.
-
- Here are some of the thinking behind it. I wanted a filter to do this,
- and I realised that I could use the 'ed' trick doing "g/^/m0" to
- reverse a file, but this would mean 'cat'ting to a temp file,
- reversing, and then 'cat'ting again. This turned out very slow for
- large files (and 'ed' had an extra temp file of it's own).
-
- I could use 'perl', using the script "print reverse ( <> )", but this
- would mean that the whole file is slurped into memory. This could be a
- problem for very large files.
-
- My perl solution is a halfway point. It limits the amount of data held
- in core. This can be set by changing "$maxbuf". If the amount of data
- read exceeds this, it is dumped to a temp file, and the process
- continues. For reversal of small files, it will be reasonably fast,
- since it is all done in core, and for larger files, the temp file stops
- the process becoming bloated. I found it worked for me.
-
- The limit "$maxbuf" is not absolute, since lines longer than "$maxbuf"
- are not split. If the length of lines is small compared to it, then it
- will be fairly faithful to this value. Something to watch out for, is
- that if the last line is missing the newline, in the output file, it
- gets glued to the next line.
-
- Over to you,
- Alfie
- --
- Nick Holloway | `O O' | alfie@cs.warwick.ac.uk, alfie@warwick.UUCP,
- [aka `Alfie'] | // ^ \\ | ..!uunet!mcsun!ukc!warwick!alfie
-
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- # reverse.pl
- # This archive created: Wed Feb 13 17:58:54 1991
- export PATH; PATH=/bin:$PATH
- if test -f 'reverse.pl'
- then
- echo shar: will not over-write existing file "'reverse.pl'"
- else
- cat << \SHAR_EOF > 'reverse.pl'
- #!/usr/local/bin/perl
-
- # Program : reverse
- # Usage : reverse [ file ... ]
- # print out lines in files given (or stdin if none) in the
- # reverse order on the standard output
- # Author : Nick Holloway <alfie@cs.warwick.ac.uk>
- # Date : 11th January 1991
- # Place : Computer Science Dept, University of Warwick, Coventry, UK
-
- # $maxbuf - maximum number of bytes to keep in core
- # $tmpdir - directory to keep temp file in (overridden by env var TMPDIR)
- # @buffer - array used to keep current set of input lines
- # @tell - array holding position and number of lines dumped to temp file
-
- #-- configuration section
- $maxbuf = 8 * 1024; # maximum number of bytes to keep in core
- $tmpdir = '/tmp'; # default temporary directory
-
- #-- let battle commence...
- $0 =~ s%.*/%%; # basename $0
-
- #-- create temp file, open for update and unlink to avoid need to clean up.
- $tmp = ( $ENV { 'TMPDIR' } || $tmpdir ) . "/reverse.$$";
- open ( TMP, "+>$tmp" )
- || die ( "$0: can't open \"$tmp\": $!\n" );
- unlink ( $tmp )
- || die ( "$0: unlink of \"$tmp\" failed: $!\n" );
-
- #-- read input, dumping reversed portions to temp file if necessary
- while ( <> ) {
- $bufsiz += length;
- if ( $bufsiz >= $maxbuf ) {
- push ( @tell, tell ( TMP ), 0+@buffer );
- print TMP reverse @buffer; # reverse, and dump buffer to file
- @buffer = (); # empty buffer
- $bufsiz = length; # new buffer size
- }
- push ( @buffer, $_ );
- }
-
- #-- print in-core buffer.
- print reverse @buffer;
-
- #-- for each section dumped to file, print these out.
- while ( @tell ) {
- $lns = pop ( @tell );
- $pos = pop ( @tell );
- seek ( TMP, $pos, 0 ) || # move to saved postion in file
- die ( "$0: can't seek in temp file: $!\n" );
- for ( 1 .. $lns ) { # print lines dumped previously
- print ''.<TMP>;
- }
- }
- SHAR_EOF
- chmod +x 'reverse.pl'
- fi # end of overwriting check
- # End of shell archive
- exit 0
-