home *** CD-ROM | disk | FTP | other *** search
- #!/usr/local/bin/kermit +
- ;
- ; m e r g e
- ;
- ; Merges any number of files, each of which is already sorted in ascending
- ; order, into a new file that is also sorted in ascending order. Blank
- ; lines are discarded. The result file is sent to standard output. The
- ; files may be of different lengths, including empty. UNIX usage, in which
- ; standard output is redirected to a file:
- ;
- ; merge file1 file2 file3 ... > output-file
- ;
- ; Requires: C-Kermit 7.0 or later.
- ; Illustrates: FOPEN/FREAD/FCLOSE operating on multiple files at once.
- ;
- ; Note syntax of comparison at bottom of FOR loop. The record array
- ; reference is accessed through \fcontents() to prevent unwanted processing
- ; of backslashes in the record, and enclosed in braces to preserve leading
- ; and trailing spaces.
- ;
- ; In this example, the sort key is the whole record. To use other sort keys
- ; or orders, modify the comparison statement accordingly. Other modifications
- ; would be needed for discarding duplicate records, flagging sequence errors
- ; in source files, etc.
- ;
- ; Author: F. da Cruz, the Kermit Project, Columbia University, July 1999
- ;
- local \%i \%n \&c[] \&r[] ; Local variables
-
- .\%n ::= (\v(argc)-1) ; Number of files from command line
-
- dcl \&c[\%n] ; Channel numbers for each file
- dcl \&r[\%n] ; Current record from each file
-
- for \%i 1 \%n 1 { ; Loop through command-line arguments
- .\&c[\%i] = -1 ; Remember which files are not open
- fopen /read \&c[\%i] \&_[\%i] ; Try to open this one
- }
- while 1 { ; Loop till done
- .\%k = -1 ; Index of next output record
- set flag off ; No records yet
- for \%i 1 \%n 1 { ; For each file...
- if < \&c[\%i] 0 continue ; Skip this one if it's not open
- while not def \&r[\%i] { ; Skip blank lines
- if \f_eof(\&c[\%i]) { ; If at end of file
- fclose \&c[\%i] ; close this file
- .\&c[\%i] = -1 ; and mark it as closed
- break
- }
- fread \&c[\%i] \&r[\%i] ; Otherwise read a record
- }
- if < \&c[\%i] 0 continue ; Next file if this file closed above
- if not flag { ; First record this round
- .\%k := \%i ; Remember its index
- set flag on ; Not first record any more
- continue ; On to next file
- }
- ; Lexically compare this record with the current smallest record
- if ( llt {\fcont(\&r[\%i])} {\fcont(\&r[\%k])} ) .\%k := \%i
- }
- if ( < \%k 0 ) break ; If no more records we're done.
- echo \&r[\%k] ; Otherwise output this record
- undef \&r[\%k] ; and force it to be replaced.
- }
- exit 0
-