home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / pub / scripts / ckermit / merge < prev    next >
Text File  |  2020-01-01  |  3KB  |  66 lines

  1. #!/usr/local/bin/kermit +
  2. ;
  3. ; m e r g e
  4. ; Merges any number of files, each of which is already sorted in ascending
  5. ; order, into a new file that is also sorted in ascending order.  Blank
  6. ; lines are discarded.  The result file is sent to standard output.  The
  7. ; files may be of different lengths, including empty.  UNIX usage, in which
  8. ; standard output is redirected to a file:
  9. ;
  10. ;   merge file1 file2 file3 ... > output-file
  11. ;
  12. ; Requires:    C-Kermit 7.0 or later.
  13. ; Illustrates: FOPEN/FREAD/FCLOSE operating on multiple files at once.
  14. ;
  15. ; Note syntax of comparison at bottom of FOR loop.  The record array
  16. ; reference is accessed through \fcontents() to prevent unwanted processing
  17. ; of backslashes in the record, and enclosed in braces to preserve leading
  18. ; and trailing spaces.
  19. ;
  20. ; In this example, the sort key is the whole record.  To use other sort keys
  21. ; or orders, modify the comparison statement accordingly.  Other modifications
  22. ; would be needed for discarding duplicate records, flagging sequence errors
  23. ; in source files, etc.
  24. ;
  25. ; Author: F. da Cruz, the Kermit Project, Columbia University, July 1999
  26. ;
  27. local \%i \%n \&c[] \&r[]             ; Local variables
  28.  
  29. .\%n ::= (\v(argc)-1)                 ; Number of files from command line
  30.  
  31. dcl \&c[\%n]                          ; Channel numbers for each file
  32. dcl \&r[\%n]                          ; Current record from each file
  33.  
  34. for \%i 1 \%n 1 {                     ; Loop through command-line arguments
  35.     .\&c[\%i] = -1                    ; Remember which files are not open
  36.     fopen /read \&c[\%i] \&_[\%i]     ; Try to open this one
  37. }
  38. while 1 {                             ; Loop till done
  39.     .\%k = -1                         ; Index of next output record
  40.     set flag off                      ; No records yet
  41.     for \%i 1 \%n 1 {                 ; For each file...
  42.         if < \&c[\%i] 0 continue      ; Skip this one if it's not open
  43.     while not def \&r[\%i] {      ; Skip blank lines
  44.             if \f_eof(\&c[\%i]) {     ; If at end of file
  45.                 fclose \&c[\%i]       ; close this file
  46.                 .\&c[\%i] = -1        ; and mark it as closed
  47.                 break
  48.             }
  49.             fread \&c[\%i] \&r[\%i]   ; Otherwise read a record
  50.         }    
  51.         if < \&c[\%i] 0 continue      ; Next file if this file closed above
  52.         if not flag {                 ; First record this round
  53.             .\%k := \%i               ; Remember its index
  54.             set flag on               ; Not first record any more
  55.             continue                  ; On to next file
  56.         }
  57.         ; Lexically compare this record with the current smallest record
  58.     if ( llt {\fcont(\&r[\%i])} {\fcont(\&r[\%k])} ) .\%k := \%i
  59.     }
  60.     if ( < \%k 0 ) break              ; If no more records we're done.
  61.     echo \&r[\%k]                     ; Otherwise output this record
  62.     undef \&r[\%k]                    ; and force it to be replaced.
  63. }
  64. exit 0
  65.