More advanced replace text in file: Difference between revisions

From NSIS Wiki
Jump to navigationJump to search
 
(24 intermediate revisions by the same user not shown)
Line 3: Line 3:
== Description ==
== Description ==
This function allows you to replace pieces of text in a file.
This function allows you to replace pieces of text in a file.
Instead of replacing all text found in the file, you have the extra option of replacing text after the x times of it occurring, and x times to replace the text after that occurrence.
You have the option of replacing text from the xth times of its occurring, and y times replacement of the text from that xth occurrence onwards.
Just copy the full code underneath in a file named: ReplaceInFile3.nsh and save it in the Include folder of your NSIS installation folder.
Just copy the full code underneath in a text file with notepad, rename it: ReplaceInFile3.nsh and save it in the Include folder of your NSIS installation folder. You should run your installer.exe file in administrator mode which grants you authorization for modifying files in directories (Otherwise the code will be overlooked with no warning).


== Usage 0 ==
== Usage 0 ==
Line 10: Line 10:
OutFile "my_installer.exe"
OutFile "my_installer.exe"


--- maybe some code
;--- maybe some code here


!include ReplaceInFile3.nsh
!include ReplaceInFile3.nsh


--- maybe some code
;--- maybe some code here


Section "my_section"
Section "my_section"


--- maybe some code
;--- maybe some code here


StrCpy $OLD_STR 'the_old_string'
StrCpy $OLD_STR 'the_old_string'
Line 28: Line 28:
StrCpy $FILE_TO_MODIFIED 'the_file_to_be_modified'
StrCpy $FILE_TO_MODIFIED 'the_file_to_be_modified'


!insertmacro ReplaceInFile $OLD_STR $FST_OCC $NR_OCC $REPLACEMENT_STR $FILE_TO_MODIFIED
!insertmacro ReplaceInFile $OLD_STR $FST_OCC $NR_OCC $REPLACEMENT_STR $FILE_TO_MODIFIED ;job done


;MessageBox MB_OK|MB_ICONINFORMATION "REPLACEMENT_STR = $REPLACEMENT_STR"
;MessageBox MB_OK|MB_ICONINFORMATION "REPLACEMENT_STR = $REPLACEMENT_STR"


--- maybe some code
;--- maybe some code here


SectionEnd
SectionEnd
Line 41: Line 41:
Push hello #text to be replaced
Push hello #text to be replaced
Push blah #replace with
Push blah #replace with
Push 3 #start replacing after 3rd occurrence
Push 3 #start replacing at the 3rd occurrence
Push 4 #replace next 4 occurrences
Push 4 #replace 4 occurrences onwards, in all
Push C:\temp1.bat #file to replace in
Push temp1.bat #file to replace in, in the current directory
  Call AdvReplaceInFile
  Call AdvReplaceInFile
</highlight-nsis>
</highlight-nsis>
Line 51: Line 51:
Push hello #text to be replaced
Push hello #text to be replaced
Push blah #replace with
Push blah #replace with
Push 3 #start replacing after 3rd occurrence
Push 3 #start replacing at 3rd occurrence
Push all #replace all other occurrences
Push all #replace all other occurrences
Push C:\temp1.bat #file to replace in
Push C:\temp1.bat #file to replace in
Line 63: Line 63:
Push all #replace all occurrences
Push all #replace all occurrences
Push all #replace all occurrences
Push all #replace all occurrences
Push C:\temp1.bat #file to replace in
Push 'C:\Program Files\temp1.info' #file to replace in
  Call AdvReplaceInFile
  Call AdvReplaceInFile
</highlight-nsis>
</highlight-nsis>
Line 71: Line 71:


/*
/*
First occurrence to be replaced: FST_OCC. FST_OCC = all, is the same as FST_OCC = 1.
First occurrence to be replaced: FST_OCC.  
   if FST_OCC greater than the number of occurences: no alteration of the file.
  FST_OCC = all, renders the same as FST_OCC = 1.
   if FST_OCC greater than the number of occurences in the file: no alteration of the file,
  FST_OCC negative or 0 will leave the file content unchanged no matter the NR_OCC value.  
Nr max of occurrences replaced onwards: NR_OCC,
Nr max of occurrences replaced onwards: NR_OCC,
   if NR_OCC = all --> replacement as long as a string to be replaced is found,
   if NR_OCC = all --> replacement as long as a string to be replaced is found,
   if NR_OCC = integer, replaces up to NR_OCC occurrences provided they exist.    
   if NR_OCC = stritly positive integer, replaces up to NR_OCC occurrences provided they exist,    
NR_OCC, FST_OCC negative will yield the same result as NR_OCC, FST_OCC equal to all.
  NR_OCC negative or 0 yields the same as all.


Order to run down and search the file: from left to right and top down.
Order to run down and search the file: from left to right and top down.
REPLACEMENT_STR, OLD_STR should be less than 1024 characters long.  
REPLACEMENT_STR, OLD_STR, read line should be less than 1024 characters long.  
For NSIS Unicode, FILE_TO_MODIFIED must be utf-8 encoded.
For NSIS Unicode, FILE_TO_MODIFIED must be utf-8 encoded.
*/
*/
Line 132: Line 134:
    
    
   FileOpen $R1 $0 r ;FILE_TO_MODIFIED file to search in
   FileOpen $R1 $0 r ;FILE_TO_MODIFIED file to search in
   FileOpen $R0 $R6 w ;temp file
   FileOpen $R0 $R6 w                   ;temp file
   StrLen $R3 $4 ;the length of OLD_STR
   StrLen $R3 $4 ;the length of OLD_STR
   StrCpy $R4 0 ;counter initialization
   StrCpy $R4 0 ;counter initialization
Line 151: Line 153:
   StrCmp $5 0 file_write ;end of line has been reached
   StrCmp $5 0 file_write ;end of line has been reached
   StrCpy $6 $7 $R3 $5 ;a chunk of read line of length OLD_STR  
   StrCpy $6 $7 $R3 $5 ;a chunk of read line of length OLD_STR  
   StrCmp $6 $4 0 loop_filter ;continues searching OLD_STR if no match
   StrCmp $6 $4 0 loop_filter ;continues to search OLD_STR if no match
   
   
StrCpy $8 $7 $5 ;left part  
StrCpy $8 $7 $5 ;left part  
Line 166: Line 168:
IntOp $R4 $R4 + 1 ;counter incrementation
IntOp $R4 $R4 + 1 ;counter incrementation
;MessageBox MB_OK|MB_ICONINFORMATION \
;MessageBox MB_OK|MB_ICONINFORMATION \
;"count 4 = $R4, fst_occ = $2"  
;"count R4 = $R4, fst_occ = $2"  
StrCmp $2 all follow_up ;exchange ok, then goes to search the next OLD_STR
StrCmp $2 all follow_up ;exchange ok, then goes to search the next OLD_STR
IntCmp $R4 $2 follow_up ;no exchange until FST_OCC has been reached,
IntCmp $R4 $2 follow_up ;no exchange until FST_OCC has been reached,
Line 176: Line 178:
IntOp $R5 $R5 + 1 ;counter incrementation
IntOp $R5 $R5 + 1 ;counter incrementation
;MessageBox MB_OK|MB_ICONINFORMATION \
;MessageBox MB_OK|MB_ICONINFORMATION \
;"count 5 = $R5, nbr_occ = $1"  
;"count R5 = $R5, nbr_occ = $1"  
StrCmp $1 all exchange_ok ;goes to exchange OLD_STR with REPLACEMENT_STR
StrCmp $1 all exchange_ok ;goes to exchange OLD_STR with REPLACEMENT_STR
IntCmp $R5 $1 finalize ;proceeding exchange until NR_OCC has been reached
IntCmp $R5 $1 finalize ;proceeding exchange until NR_OCC has been reached


exchange_ok:
exchange_ok:
IntOp $5 $5 + $R3 ;updating counter
IntOp $5 $5 + $R3 ;updating cursor
StrCpy $7 $9 ;updating read line with forster read line
StrCpy $7 $9 ;updating read line with forster read line
Goto loop_filter ;goes searching the same read line
Goto loop_filter ;goes searching the same read line
Line 227: Line 229:
; 2020-12-12
; 2020-12-12
: Mild alterations to make it work, and such as it was intended to in the first place. Pascal Dor.
: Mild alterations to make it work, and such as it was intended to in the first place. Pascal Dor.
:bug: browses the read line from right to left
:bug: scans the read line from right to left
:bug: doesn't do the job unless: FST_OCC = NR_OCC = all, and even so not fully.  
:bug: doesn't do the job unless: FST_OCC = NR_OCC = all, and even so not fully.  



Latest revision as of 17:45, 14 December 2020

Author: Afrow UK (talk, contrib)


Description

This function allows you to replace pieces of text in a file. You have the option of replacing text from the xth times of its occurring, and y times replacement of the text from that xth occurrence onwards. Just copy the full code underneath in a text file with notepad, rename it: ReplaceInFile3.nsh and save it in the Include folder of your NSIS installation folder. You should run your installer.exe file in administrator mode which grants you authorization for modifying files in directories (Otherwise the code will be overlooked with no warning).

Usage 0

OutFile "my_installer.exe"
 
;--- maybe some code here
 
!include ReplaceInFile3.nsh
 
;--- maybe some code here
 
Section "my_section"
 
;--- maybe some code here
 
StrCpy $OLD_STR 'the_old_string'
StrCpy $FST_OCC all
StrCpy $FST_OCC 2
StrCpy $NR_OCC all
StrCpy $NR_OCC 3
StrCpy $REPLACEMENT_STR 'the_new_string'
StrCpy $FILE_TO_MODIFIED 'the_file_to_be_modified'
 
!insertmacro ReplaceInFile $OLD_STR $FST_OCC $NR_OCC $REPLACEMENT_STR $FILE_TO_MODIFIED ;job done
 
;MessageBox MB_OK|MB_ICONINFORMATION "REPLACEMENT_STR = $REPLACEMENT_STR"
 
;--- maybe some code here
 
SectionEnd

Usage 1

Push hello #text to be replaced
Push blah #replace with
Push 3 #start replacing at the 3rd occurrence
Push 4 #replace 4 occurrences onwards, in all
Push temp1.bat #file to replace in, in the current directory
 Call AdvReplaceInFile

Usage 2

Push hello #text to be replaced
Push blah #replace with
Push 3 #start replacing at 3rd occurrence
Push all #replace all other occurrences
Push C:\temp1.bat #file to replace in
 Call AdvReplaceInFile

Usage 3

Push hello #text to be replaced
Push blah #replace with
Push all #replace all occurrences
Push all #replace all occurrences
Push 'C:\Program Files\temp1.info' #file to replace in
 Call AdvReplaceInFile

Code

/*
First occurrence to be replaced: FST_OCC. 
   FST_OCC = all, renders the same as FST_OCC = 1.
   if FST_OCC greater than the number of occurences in the file: no alteration of the file,
   FST_OCC negative or 0 will leave the file content unchanged no matter the NR_OCC value. 
Nr max of occurrences replaced onwards: NR_OCC,
   if NR_OCC = all --> replacement as long as a string to be replaced is found,
   if NR_OCC = stritly positive integer, replaces up to NR_OCC occurrences provided they exist,   
   NR_OCC negative or 0 yields the same as all.
 
Order to run down and search the file: from left to right and top down.
REPLACEMENT_STR, OLD_STR, read line should be less than 1024 characters long. 
For NSIS Unicode, FILE_TO_MODIFIED must be utf-8 encoded.																	
*/
 
Var /Global OLD_STR
Var /Global FST_OCC
Var /Global NR_OCC
Var /Global REPLACEMENT_STR
Var /Global FILE_TO_MODIFIED
 
!macro ReplaceInFile OLD_STR FST_OCC NR_OCC REPLACEMENT_STR FILE_TO_MODIFIED
 
        Push "${OLD_STR}" ;text to be replaced
	Push "${REPLACEMENT_STR}" ;replace with
	Push "${FST_OCC}" ; starts replacing onwards FST_OCC occurrences
	Push "${NR_OCC}" ; replaces NR_OCC occurrences in all
	Push "${FILE_TO_MODIFIED}" ; file to replace in
	Call AdvReplaceInFile
 
!macroend
 
 
Function AdvReplaceInFile
Exch $0 ;FILE_TO_MODIFIED file to replace in
Exch
Exch $1 ;the NR_OCC of OLD_STR occurrences to be replaced.
Exch
Exch 2
Exch $2 ;FST_OCC: the first occurrence to be replaced and onwards
Exch 2
Exch 3
Exch $3 ;REPLACEMENT_STR string to replace with
Exch 3
Exch 4
Exch $4 ;OLD_STR to be replaced
Exch 4
Push $5 ;incrementing counter
Push $6 ;a chunk of read line
Push $7 ;the read line altered or not
Push $8 ;left string
Push $9 ;right string or forster read line
Push $R0 ;temp file handle
Push $R1 ;FILE_TO_MODIFIED file handle
Push $R2 ;a line read
Push $R3 ;the length of OLD_STR
Push $R4 ;counts reaching of FST_OCC
Push $R5 ;counts reaching of NR_OCC
Push $R6 ;temp file name
 
 
  GetTempFileName $R6
 
  FileOpen $R1 $0 r 			;FILE_TO_MODIFIED file to search in
  FileOpen $R0 $R6 w                    ;temp file
   StrLen $R3 $4			;the length of OLD_STR
   StrCpy $R4 0				;counter initialization
   StrCpy $R5 -1			;counter initialization
 
loop_read:
 ClearErrors
 FileRead $R1 $R2 			;reading line
 IfErrors exit				;when end of file has been reached
 
   StrCpy $5 -1  			;cursor, start of read line chunk
   StrLen $7 $R2 			;read line length
   IntOp $5 $5 - $7			;cursor initialization
   StrCpy $7 $R2			;$7 contains read line
 
loop_filter:
   IntOp $5 $5 + 1 			;cursor shifting
   StrCmp $5 0 file_write		;end of line has been reached
   StrCpy $6 $7 $R3 $5 			;a chunk of read line of length OLD_STR 
   StrCmp $6 $4 0 loop_filter		;continues to search OLD_STR if no match
 
StrCpy $8 $7 $5 			;left part 
IntOp $6 $5 + $R3
IntCmp $6 0 yes no			;left part + OLD_STR == full line read ?						
yes:
StrCpy $9 ""
Goto done
no:
StrCpy $9 $7 "" $6 			;right part
done:
StrCpy $9 $8$3$9 			;replacing OLD_STR by REPLACEMENT_STR in forster read line
 
IntOp $R4 $R4 + 1			;counter incrementation
;MessageBox MB_OK|MB_ICONINFORMATION \
;"count R4 = $R4, fst_occ = $2" 
StrCmp $2 all follow_up			;exchange ok, then goes to search the next OLD_STR
IntCmp $R4 $2 follow_up			;no exchange until FST_OCC has been reached,
Goto loop_filter			;and then searching for the next OLD_STR
 
follow_up:	
IntOp $R4 $R4 - 1			;now counter is to be stuck to FST_OCC
 
IntOp $R5 $R5 + 1			;counter incrementation
;MessageBox MB_OK|MB_ICONINFORMATION \
;"count R5 = $R5, nbr_occ = $1" 
StrCmp $1 all exchange_ok 		;goes to exchange OLD_STR with REPLACEMENT_STR
IntCmp $R5 $1 finalize			;proceeding exchange until NR_OCC has been reached														
 
exchange_ok:
IntOp $5 $5 + $R3 			;updating cursor
StrCpy $7 $9				;updating read line with forster read line
Goto loop_filter			;goes searching the same read line
 
finalize:
IntOp $R5 $R5 - 1			;now counter is to be stuck to NR_OCC
 
file_write: 
 FileWrite $R0 $7 			;writes altered or unaltered line 
Goto loop_read				;reads the next line
 
exit:
  FileClose $R0
  FileClose $R1
 
   ;SetDetailsPrint none
  Delete $0
  Rename $R6 $0				;superseding FILE_TO_MODIFIED file with
					;temp file built with REPLACEMENT_STR 
  ;Delete $R6
   ;SetDetailsPrint lastused
 
Pop $R6
Pop $R5
Pop $R4
Pop $R3
Pop $R2
Pop $R1
Pop $R0
Pop $9
Pop $8
Pop $7
Pop $6
Pop $5
;These values are stored in the stack in the reverse order they were pushed
Pop $0
Pop $1
Pop $2
Pop $3
Pop $4
FunctionEnd

Versions History

2020-12-12
Mild alterations to make it work, and such as it was intended to in the first place. Pascal Dor.
bug: scans the read line from right to left
bug: doesn't do the job unless: FST_OCC = NR_OCC = all, and even so not fully.
2010-10-09
Bug fixed that doesn't change "all" occurrences
2006-09-28
Bug fixed that restoring $0~$4 order -- Maxi Ng
2005-July-18
Bug fixed that doesn't replace a text when you have only 1 line in the text file - Mark Bryan Yu
2004-Feb-18
Bug fixed that stopped it replacing parts of text on a line. The bug was only allowing it to replace whole lines.
2003-May-27
Re-written.

Credits

Written by me for modifying batch files.

-Stu (Afrow UK)