Here is some simple code that we use to do a mass replace of text strings in physical file source members. It does a case sensitive search and replaces the entire search string with the replacement sting and will always produce data shift if the search and replacement strings are of different lengths.

The search and replace is performed with a few simple lines of SQL embedded within some equally simple ILE RPG code.

Here is the command source that is used to prompt the ILE RPG program:

        CMD PROMPT('Mass replace in Source Members')

        PARM KWD(SOURCE) TYPE(SOURCE) MIN(1) +
        PROMPT('Source File eg QRPGLESRC')

SOURCE: QUAL TYPE(*NAME) LEN(10) MIN(1)
        QUAL TYPE(*NAME) LEN(10) DFT(*LIBL) +
        SPCVAL((*LIBL) (*CURLIB)) PROMPT('Library')

        PARM KWD(FROMSTR) TYPE(*CHAR) LEN(130) RSTD(*NO) +
        MIN(1) ALWUNPRT(*NO) FULL(*NO) +
        CASE(*MIXED) PROMPT('Find String')

        PARM KWD(TOSTR) TYPE(*CHAR) LEN(130) RSTD(*NO) +
        MIN(1) ALWUNPRT(*NO) FULL(*NO) +
        CASE(*MIXED) PROMPT('Replacement String')

… and here is the ILE RPG with the embedded SQL that performs the search and replace:

**free                                                                                                                                    
                                                                                                                                          
// Example program to mass replace a search string by a replacement string in source members of                                           
// a source physical file eg QRPGLESRC etc. Use with caution. It is advisable to back your                                                
// source up before you perform a mass replace. The SQL used to perform the search has been                                               
// coded to be case sensitive and will cause data shift where the replacement string is longer                                            
// or shorter than the search string. Leading spaces will be included while trailing spaces                                               
// will be trimmed. This logic could be changed with different SQL options.                                                               
                                                                                                                                          
//---------------------------------------------------------------------------------------------//                                         
// All source code included in this document are provided on an "AS IS" basis without warranty //                                         
// of any kind. NOVAGEM WILL NOT BE LIABLE FOR ANY ACTUAL, DIRECT, SPECIAL, INCIDENTAL, OR     //                                         
// INDIRECT DAMAGES OR FOR ANY ECONOMIC CONSEQUENTIAL DAMAGES INCLUDING LOST PROFITS OR        //                                         
// SAVINGS.                                                                                    //                                         
//---------------------------------------------------------------------------------------------//                                         
                                                                                                                                          
// Novagem Ltd                                                                                                                            
                                                                                                                                          
ctl-opt dftactgrp(*NO) option(*NOSHOWCPY:*NODEBUGIO);                                                                                     
                                                                                                                                          
dcl-ds qusec;                                                                                                                             
 qusbprv int(10) inz(%size(qusec));                                                                                                       
 qusbavl int(10) inz(0);                                                                                                                  
 qusei char(7);                                                                                                                           
 *N char(1);                                                                                                                              
 msgdata char(200);                                                                                                                       
end-ds;                                                                                                                                   
                                                                                                                                          
dcl-ds errorCode likeds(qusec);                                                                                                           
                                                                                                                                          
dcl-s qCmd char(6000);                                                                                                                    
dcl-s FROMSTRwithPercents char(132);                                                                                                      
dcl-s MLFILE char(10);                                                                                                                    
dcl-s MLLIB char(10);                                                                                                                     
dcl-s MLNAME char(10);                                                                                                                    
dcl-s MLSEU2 char(10);                                                                                                                    
dcl-s msgDta char(3000);                                                                                                                  
dcl-s msgKey char(4);                                                                                                                     
dcl-s noOfReplacements int(10);                                                                                                           
dcl-s sqlMsg char(2000);                                                                                                                  
dcl-s sqlStmt char(2000);                                                                                                                 
                                                                                                                                          
dcl-ds srcFNamLib;                                                                                                                        
 srcFNam char(10);                                                                                                                        
 srcFLib char(10);                                                                                                                        
end-ds;                                                                                                                                   
                                                                                                                                          
dcl-pr QMHSNDPM extpgm;                                                                                                                   
 msgID char(7) const;                                                                                                                     
 msgFile char(20) const;                                                                                                                  
 msgDta char(32767) options(*varsize) const;                                                                                              
 msgDtaLen int(10) const;                                                                                                                 
 msgType char(10) const;                                                                                                                  
 stackEntry char(10) const;                                                                                                               
 StackCount int(10) const;                                                                                                                
 msgKey char(4);                                                                                                                          
 error char(1024) options(*varsize) noopt;                                                                                                
end-pr;                                                                                                                                   
                                                                                                                                          
dcl-pr QCMDEXC extpgm;                                                                                                                    
 *n char(6000) options(*varsize) const;                                                                                                   
 *n packed(15:5) const;                                                                                                                   
end-pr;                                                                                                                                   
                                                                                                                                          
dcl-pi MASSRPL;                                                                                                                           
 SOURCE char(20);                                                                                                                         
 FROMSTR char(130);                                                                                                                       
 TOSTR char(130);                                                                                                                         
end-pi;                                                                                                                                   
                                                                                                                                          
// Create a temporary file and populate it with a list of members contained in the source physical file                                   
srcFNamLib=SOURCE;                                                                                                                        
qCmd='DSPFD FILE('+%trim(srcFLib)+'/'+%trim(srcFNam)+') TYPE(*MBRLIST) OUTPUT(*OUTFILE) OUTFILE(QTEMP/MRMBRLIST)';                        
QCMDEXC(qCmd:%Len(%trimr(qCmd)));                                                                                                         
                                                                                                                                          
// *****                                                                                                                                  
dow 0=0;                                                                                                                                  
// *****                                                                                                                                  
                                                                                                                                          
 // Retrieve next row from member list table                                                                                              
 exec sql SELECT MLFILE,MLLIB,MLNAME,MLSEU2 INTO :MLFILE,:MLLIB,:MLNAME,:MLSEU2 FROM MRMBRLIST FETCH FIRST 1 ROWS ONLY;                   
 if SQLSTATE<>'00000'; // Exit if EOF reached                                                                                             
  msgDta=%trim(%char(noOfReplacements))+' replacements completed successfully.';                                                          
  QMHSNDPM(' ':' ':%trim(msgDta):%len(%trim(msgDta)):'*INFO':'*PGMBDY':1:msgKey:errorCode); // Send completion message                    
  leave;                                                                                                                                  
 endif;                                                                                                                                   
                                                                                                                                          
 // Create alias to point at source file member                                                                                           
 exec sql DROP ALIAS QTEMP/NXTMBR;                                                                                                        
 sqlStmt = 'CREATE ALIAS QTEMP/NXTMBR FOR '+%trim(srcFLib)+'/'+%trim(srcFNam)+' ('+%trim(MLNAME)+')';                                     
 exec sql EXECUTE IMMEDIATE :sqlStmt;                                                                                                     
 if SQLSTATE<>'00000';                                                                                                                    
  msgDta='Unable to create alias on '+%trim(srcFLib)+'/'+%trim(srcFNam)+'.'+%trim(MLNAME);                                                
  exsr GetErrorText;                                                                                                                      
  leave;                                                                                                                                  
 endif;                                                                                                                                   
                                                                                                                                          
 // Perform replacement of string in member                                                                                               
 FROMSTRwithPercents='%'+%trimr(FROMSTR)+'%';                                                                                             
 exec sql UPDATE NXTMBR SET SRCDTA = REPLACE(SRCDTA,TRIM(TRAILING FROM :FROMSTR),TRIM(TRAILING FROM :TOSTR))                              
  WHERE SRCDTA LIKE TRIM(:FROMSTRwithPercents) WITH NC;                                                                                   
 if SQLSTATE<>'00000' and // Test for error                                                                                               
    SQLSTATE<>'02000';                                                                                                                    
  msgDta='Unable to update mbr '+%trim(srcFLib)+'/'+%trim(srcFNam)+'.'+%trim(MLNAME);                                                     
  exsr GetErrorText;                                                                                                                      
  leave;                                                                                                                                  
 endif;                                                                                                                                   
 noOfReplacements=noOfReplacements+SQLERRD(3); // Bump counter for number of members processed                                            
                                                                                                                                          
 // Delete row from table                                                                                                                 
 exec sql DELETE FROM QTEMP/MRMBRLIST WHERE MLLIB=:MLLIB AND MLFILE=:MLFILE AND MLNAME=:MLNAME WITH NC;                                   
                                                                                                                                          
// ***                                                                                                                                    
enddo;                                                                                                                                    
// ***                                                                                                                                    
                                                                                                                                          
*INLR=*ON;                                                                                                                                
return;                                                                                                                                   
                                                                                                                                          
// ****************                                                                                                                       
begsr GetErrorText;                                                                                                                       
// ****************                                                                                                                       
                                                                                                                                          
// Get error diagnostic info and output msg to screen                                                                                     
exec sql GET DIAGNOSTICS CONDITION 1 :sqlMsg = MESSAGE_TEXT;                                                                              
msgDta=%trim(msgDta)+': '+sqlMsg;                                                                                                         
QMHSNDPM(' ':' ':%trim(msgDta):%len(%trim(msgDta)):'*INFO':'*PGMBDY':1:msgKey:errorCode);                                                 
                                                                                                                                          
// ***                                                                                                                                    
endsr;                                                                                                                                    
// ***                                                                                                                                    

Walk through

On line 73 we create a list of source members in the chosen source physical in a temporary table in QTEMP using the command DSPFD.

Then on line 81 we read the next record from the previously created temporary table checking for EOF at which point we output the completion message and exit the program.

On line 90 we create an alias in SQL (NXTMBR) which allows SQL to access the particular member retrieved in the row from the table above.

Then on line 100 we perform the search and replace using an SQL update statement which references the aliased member defined on line 90 checking for any error codes and outputting the SQL diagnostics if any errors occur.

The row from the temporary member list table is then deleted on line 111 and the loop is processed again starting with fetching the next row from the table.

We have called the ILE RPG program MASSRPL and named and compiled the command accordingly. As always it’s advisable to backup your source before performing any mass replace operations.