/* REXX */ /* */ /* AUTHOR: Mark Zelden */ /* Last Updated 04/01/2005 */ /* */ /* TRACE ?R */ Arg SORTIN SORTOUT OUTFILE DUPFILE COL1 COL2 EQUALS /* */ /* This exec will sort a file and delete records that have */ /* duplicate characters between user specified columns. */ /* It will also write the duplicate records to another file. */ /* */ /* REQUIRED POSITIONAL PARAMETERS: - (do not use quotes) */ /* SORTIN - input dataset name */ /* SORTOUT - sorted output dataset with duplicates */ /* OUTFILE - sorted output dataset without duplicates */ /* DUPFILE - sorted output dataset of only duplicates */ /* COL1 - the beginning sort column */ /* COL2 - the length of the sort */ /* */ /* OPTIONAL POSITIONAL PARAMETER: EQUALS */ /* */ /* ** NOTE*** ALL FILES MUST BE PRE-ALLOCATED AND HAVE THE */ /* SAME ATTRIBUTES AS THE SORTIN FILE */ /* (SORTIN & SORTOUT CAN BE THE SAME FILE). */ /* */ /* SAMPLE EXECUTION FROM ISPF OPT 6: */ /* */ /* %DELDUPS2 USERID.SORTIN USERID.SORTOUT USERID.OUTFILE */ /* USERID.DUPFILE 4 20 */ /* */ /* SAMPLE EXECUTION FROM BATCH: */ /* */ /* //MYJOB JOB (ACCT),CLASS=E,MSGCLASS=H */ /* //TMP EXEC PGM=IKJEFT01,REGION=2M,DYNAMNBR=20 */ /* //SYSPROC DD DSN=CLIST.LIBRARY,DISP=SHR */ /* //SYSTSPRT DD SYSOUT=* */ /* //SYSTSIN DD DATA,DLM=## */ /* %DELDUPS2 + */ /* USERID.SORTIN + */ /* USERID.SORTOUT + */ /* USERID.OUTFILE + */ /* USERID.DUPFILE + */ /* 1 9 EQUALS */ /* ## */ /* // */ /* */ /* check for numeric column numbers */ If COL1 <> '' then do If Datatype(COL1,Number) <> 1 then do Say '************************************' Say 'THE STARTING COLUMN MUST BE NUMERIC.' Say '************************************' Exit 12 End End If COL2 <> '' then do If Datatype(COL2,Number) <> 1 then do Say '**********************************' Say 'THE ENDING COLUMN MUST BE NUMERIC.' Say '**********************************' Exit 12 End End If SORTIN = '' then call MISSING_PARMS If SORTOUT = '' then call MISSING_PARMS If OUTFILE = '' then call MISSING_PARMS If DUPFILE = '' then call MISSING_PARMS If COL1 = '' then call MISSING_PARMS If COL2 = '' then call MISSING_PARMS If EQUALS <> '' then do If EQUALS <> 'EQUALS' then call MISSING_PARMS End /***********************************/ /* Allocate files */ /***********************************/ "ALLOC DA('"SORTIN"') F(SORTIN) SHR REUSE" If RC <> 0 then exit 12 "ALLOC DA('"SORTOUT"') F(SORTOUT) SHR REUSE" If RC <> 0 then exit 12 "ALLOC DA('"OUTFILE"') F(OUTFILE) SHR REUSE" If RC <> 0 then exit 12 "ALLOC DA('"DUPFILE"') F(DUPFILE) SHR REUSE" If RC <> 0 then exit 12 "ALLOC FILE(SORTWK01) UNIT(SYSDA) NEW CYL SPACE(50,50) DELETE REUSE" "ALLOC FILE(SORTWK02) UNIT(SYSDA) NEW CYL SPACE(50,50) DELETE REUSE" "ALLOC FILE(SYSOUT) DUMMY REUSE" "ALLOC FILE(SYSIN) UNIT(SYSDA) NEW TRACKS SPACE(1,1) DELETE REUSE", " LRECL(80) RECFM(F) BLKSIZE(80)" If EQUALS = 'EQUALS' then Push ' SORT FIELDS=('COL1','COL2',CH,A),EQUALS' Else Push ' SORT FIELDS=('COL1','COL2',CH,A)' "EXECIO 1 DISKW SYSIN (FINIS" /* Say '...SORTING' */ Address LINKMVS "SORT" If RC <> 0 then do Say '*******************************************' Say '* SORT FAILURE - ABENDING *' Say '*******************************************' Call FREE_FILES Exit 12 End /* Say '...SEARCHING FOR DUPLICATES' */ /***********************************/ /* Begin search for duplicates. */ /***********************************/ COUNT = 0 /* count of deleted records */ KEPT = 0 /* count of kept records */ RECNUM = 1 /* current record number */ "EXECIO" 1 "DISKR SORTOUT" RECNUM /* copy the data in the first record to variable 'DATA1' */ Parse pull DATA1 RECNUM = RECNUM + 1 Push DATA1 "EXECIO 1 DISKW OUTFILE" KEPT = KEPT + 1 CHECK1 = Substr(DATA1,COL1,COL2) Do forever /* copy the data in the next record to variable 'DATA2' */ "EXECIO" 1 "DISKR SORTOUT" RECNUM If rc <> 0 then leave /* no more records - exit */ Parse pull DATA2 RECNUM = RECNUM + 1 CHECK2 = Substr(DATA2,COL1,COL2) If CHECK2 == CHECK1 then do /* dup found - write to dupfile & check next record */ Push DATA2 "EXECIO 1 DISKW DUPFILE" COUNT = COUNT + 1 End Else do /* no dup found - write to outfile replace DATA1 & check again */ Push DATA2 "EXECIO 1 DISKW OUTFILE" KEPT = KEPT + 1 DATA1 = DATA2 CHECK1 = CHECK2 End End /* do forever */ /******************************************/ /* Done with processing - write totals */ /******************************************/ If COUNT = 0 then do Say '********************************************' Say 'NO DUPLICATE RECORDS WERE FOUND IN THE FILE.' Say '********************************************' Call FREE_FILES Exit 12 End Else do TOTAL = COUNT + KEPT Say '**********************************************************' Say TOTAL' RECORDS WERE SEARCHED FOR DUPLICATES.' Say KEPT' DIFFERENT RECORDS WERE WRITTEN TO THE OUTFILE.' Say COUNT' DUPLICATE RECORDS WERE WRITTEN TO THE DUPFILE.' Say '**********************************************************' Call FREE_FILES Exit 0 End MISSING_PARMS: Say '*********************************************************' Say '* ALL PARAMETERS WERE NOT ENTERED PROPERLY. *' Say '*********************************************************' Say '* *' Say '* REQUIRED POSITIONAL PARAMETERS: - (DO NOT USE QUOTES) *' Say '* *' Say '* SORTIN - INPUT DATASET NAME *' Say '* SORTOUT - SORTED OUTPUT DATASET WITH DUPLICATES *' Say '* OUTFILE - SORTED OUTPUT DATASET WITHOUT DUPLICATES *' Say '* DUPFILE - SORTED OUTPUT DATASET OF ONLY DUPLICATES *' Say '* COL1 - THE BEGINNING SORT COLUMN *' Say '* COL2 - THE LENGTH OF THE SORT *' Say '* *' Say '* OPTIONAL POSITIONAL PARAMETER: EQUALS *' Say '* *' Say '* *' Say '* >>> NOTE - ALL FILES MUST BE PRE-ALLOCATED AND HAVE *' Say '* THE SAME ATTRIBUTES AS THE SORTIN FILE. *' Say '* (SORTIN AND SORTOUT CAN BE THE SAME FILE). *' Say '*********************************************************' Exit 12 FREE_FILES: "EXECIO 0 DISKR SORTOUT (FINIS" "EXECIO 0 DISKW OUTFILE (FINIS" "EXECIO 0 DISKW DUPFILE (FINIS" "FREE F(SORTIN)" "FREE F(SORTOUT)" "FREE F(OUTFILE)" "FREE F(DUPFILE)" "FREE F(SORTWK01)" "FREE F(SORTWK02)" "FREE F(SYSOUT)" "FREE F(SYSIN)" Return