goer@ellis.uchicago.edu (Richard L. Goerwitz) (02/16/91)
In article <*||&R~@warwick.ac.uk> alfie@cs.warwick.ac.uk (Nick Holloway) writes: >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 ... ]" Just for fun, I did this in Icon. The difference here is that the Icon program I just wrote replaces the original with the reversed file. It's easy enough to reverse its effects. Just run it again on the same files. The usage is also somewhat different: revlines [-maxbuf] files where maxbuf is the biggest chunk to be kept in core memory, without being written to a tempfile, and where files are the names of the files to be reversed (there can be any number of them). Oh. This program will work under MS-DOS, too, with its different path conventions (i.e. \ for /). It was easy enough to add support for it, so I did. This is not an extensively tested program, and since it's a single file, I didn't even bother to archive it. -Richard (goer@sophist.uchicago.edu) ############################################################################ # # Name: revlines.icn # # Title: reverse lines in file # # Author: Richard L. Goerwitz # # Version: 1.1 # ############################################################################ # # Revlines reverses the order of lines in one or more files, using # temporary files if the sorting requires keeping more than a user- # specifiable amount of text in memory. Usage is # # revlines [-maxsize] files # # where maxsize represents the maximum file size to be sorted in core # memory without using temporary files, and where files representes # one or more filenames to be reversed. # # If you want to reverse the effects of revlines, run it again on the # file(s) in question. They will end up precisely as they started # out before the first run of revlines. # ############################################################################ # # Links: none # # Requires: UNIX or MS-DOS, co-expressions # ############################################################################ global filename, get_tempname procedure main(a) local usage, tempnames, max, intext, loc, lines, outtext, final_tempname usage := "usage: revlines [-maxsize] files" # where maxsize refers to the maximum bytes to hold in memory # before using temp files (default 262,000) if match("-",a[1]) then max := integer(pop(a)) | stop(usage) else max := 262001 # approximate max <:= 255 *a = 0 & stop(usage) every filename := !a do { tempnames := [] get_tempname := create |gimme_a_temp() if not (intext := open(filename)) then write(&errout, "revlines: can't open ",filename) else { repeat { lines := [] loc := where(intext) + max until where(intext) >= loc do push(lines, read(intext)) | break if *lines = 0 then break else { outtext := open(tempname := |@get_tempname, "w") | abort(tempnames) push(tempnames, tempname) every write(outtext, !lines) close(outtext) } } close(intext) if *tempnames = 0 then write(&errout,"revlines: ", filename, " is empty!") else { outtext := open(final_tempname := |@get_tempname, "w") | abort(tempnames) every tempname := !tempnames do { if not (intext := open(tempname)) then { close(outtext) abort(tempnames ||| [final_tempname]) } every write(outtext, !intext) close(intext) } close(outtext) every remove(!tempnames|filename) if not rename(final_tempname, filename) then { remove(final_tempname) stop("revlines: can't replace ", filename, " with tempfile ",final_tempname) } } } } end procedure gimme_a_temp() local tempf, temp_name static slash, nonos, replc initial { if find("MS-DOS", &features) then slash := "\\" else if find("UNIX", &features) then slash := "/" else stop("revlines: unsupported operating system") nonos := ~(&letters ++ &digits) replc := left(~nonos,*nonos,"Z") } filename ? { tempf := "" while tempf ||:= tab(find(slash)+1) tempf := getenv("TEMPDIR") tempf ||:= map(tab(0)[-8:0] | right(tab(0),8,"X"), nonos, replc) } every temp_name := tempf || "." || right(1 to 999,3,"0") do { close(open(temp_name)) & next suspend \temp_name } end procedure abort(l) write(&errout, "revlines: can't open temp file; aborting") every remove(!l) exit(2) end