More advanced replace text in file: Difference between revisions
From NSIS Wiki
Jump to navigationJump to search
m (Added category links.) |
(→Code) |
||
(56 intermediate revisions by 9 users not shown) | |||
Line 1: | Line 1: | ||
{{PageAuthor|Afrow UK}} | |||
== 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. | ||
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 == | |||
<highlight-nsis> | |||
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 | |||
</highlight-nsis> | |||
== Usage 1 == | == Usage 1 == | ||
Line 11: | 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 | Push 3 #start replacing at the 3rd occurrence | ||
Push 4 #replace | Push 4 #replace 4 occurrences onwards, in all | ||
Push | Push temp1.bat #file to replace in, in the current directory | ||
Call AdvReplaceInFile | Call AdvReplaceInFile | ||
</highlight-nsis> | </highlight-nsis> | ||
Line 21: | 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 | 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 33: | 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. | Push 'C:\Program Files\temp1.info' #file to replace in | ||
Call AdvReplaceInFile | Call AdvReplaceInFile | ||
</highlight-nsis> | </highlight-nsis> | ||
== | == Code == | ||
<highlight-nsis> | <highlight-nsis> | ||
/* | |||
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 | Function AdvReplaceInFile | ||
Exch $0 ;file to replace in | Exch $0 ;FILE_TO_MODIFIED file to replace in | ||
Exch | Exch | ||
Exch $1 ; | Exch $1 ;the NR_OCC of OLD_STR occurrences to be replaced. | ||
Exch | Exch | ||
Exch 2 | Exch 2 | ||
Exch $2 ; | Exch $2 ;FST_OCC: the first occurrence to be replaced and onwards | ||
Exch 2 | Exch 2 | ||
Exch 3 | Exch 3 | ||
Exch $3 ;replace with | Exch $3 ;REPLACEMENT_STR string to replace with | ||
Exch 3 | Exch 3 | ||
Exch 4 | Exch 4 | ||
Exch $4 ;to | Exch $4 ;OLD_STR to be replaced | ||
Exch 4 | Exch 4 | ||
Push $5 ; | Push $5 ;incrementing counter | ||
Push $6 ; | Push $6 ;a chunk of read line | ||
Push $7 ; | Push $7 ;the read line altered or not | ||
Push $8 ;left string | Push $8 ;left string | ||
Push $9 ;right string | Push $9 ;right string or forster read line | ||
Push $R0 ; | Push $R0 ;temp file handle | ||
Push $R1 ; | Push $R1 ;FILE_TO_MODIFIED file handle | ||
Push $R2 ;read | Push $R2 ;a line read | ||
Push $R3 ; | Push $R3 ;the length of OLD_STR | ||
Push $R4 ; | Push $R4 ;counts reaching of FST_OCC | ||
Push $R5 ; | Push $R5 ;counts reaching of NR_OCC | ||
Push $R6 ;temp file name | Push $R6 ;temp file name | ||
GetTempFileName $R6 | GetTempFileName $R6 | ||
FileOpen $R1 $0 r ;file to search in | |||
FileOpen $R0 $R6 w ;temp file | FileOpen $R1 $0 r ;FILE_TO_MODIFIED file to search in | ||
StrLen $R3 $4 | FileOpen $R0 $R6 w ;temp file | ||
StrCpy $R4 | StrLen $R3 $4 ;the length of OLD_STR | ||
StrCpy $R5 -1 | StrCpy $R4 0 ;counter initialization | ||
StrCpy $R5 -1 ;counter initialization | |||
loop_read: | loop_read: | ||
ClearErrors | ClearErrors | ||
FileRead $R1 $R2 ; | FileRead $R1 $R2 ;reading line | ||
IfErrors exit | IfErrors exit ;when end of file has been reached | ||
StrCpy $5 | StrCpy $5 -1 ;cursor, start of read line chunk | ||
StrCpy $7 $R2 | StrLen $7 $R2 ;read line length | ||
IntOp $5 $5 - $7 ;cursor initialization | |||
StrCpy $7 $R2 ;$7 contains read line | |||
loop_filter: | loop_filter: | ||
IntOp $5 $5 | IntOp $5 $5 + 1 ;cursor shifting | ||
StrCpy $6 $7 $R3 $5 ; | 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 | 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 | IntOp $R4 $R4 + 1 ;counter incrementation | ||
StrCmp $2 all | ;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 | |||
IntOp $R5 $R5 + 1 | follow_up: | ||
IntOp $R4 $R4 - 1 ;now counter is to be stuck to FST_OCC | |||
StrCmp | |||
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 | |||
Goto | 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: | exit: | ||
FileClose $R0 | FileClose $R0 | ||
FileClose $R1 | FileClose $R1 | ||
SetDetailsPrint none | ;SetDetailsPrint none | ||
Delete $0 | Delete $0 | ||
Rename $R6 $0 | Rename $R6 $0 ;superseding FILE_TO_MODIFIED file with | ||
Delete $R6 | ;temp file built with REPLACEMENT_STR | ||
SetDetailsPrint | ;Delete $R6 | ||
;SetDetailsPrint lastused | |||
Pop $R6 | Pop $R6 | ||
Pop $R5 | Pop $R5 | ||
Line 133: | Line 217: | ||
Pop $6 | Pop $6 | ||
Pop $5 | 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 | Pop $4 | ||
FunctionEnd | FunctionEnd | ||
</highlight-nsis> | </highlight-nsis> | ||
== Versions History == | == 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 | ; 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. | : Bug fixed that stopped it replacing parts of text on a line. The bug was only allowing it to replace whole lines. | ||
Line 153: | Line 252: | ||
-Stu (Afrow UK) | -Stu (Afrow UK) | ||
[[ | [[Category:Text Files Manipulation Functions]] |
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)