alfie@cs.warwick.ac.uk (Nick Holloway) (02/15/91)
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
eichin@athena.mit.edu (Mark W. Eichin) (02/16/91)
|> 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 BSD utilities include the "tac" program ("cat" in reverse :-) so that might be a better name for it. (I'm adding it to my perl-shell collection - it'll look for a perl script to do almost any command, only exec'ing a real command as a last resort... It's nice having a "truly" portable environment :-) _Mark_ <eichin@athena.mit.edu> MIT Student Information Processing Board -- Perl is the Yiddish of computer languages...