#!/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