More advanced replace text in file: Difference between revisions
Line 36: | Line 36: | ||
</highlight-nsis> | </highlight-nsis> | ||
== | /* | ||
First occurrence to be replaced: FST_OCC. FST_OCC = all, is the same as FST_OCC = 1. | |||
if FST_OCC greater than the number of occurences: no alteration of the file | |||
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 = 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. | |||
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. | |||
*/ | |||
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}" ; start replacing after FST_OCC occurrences | |||
Push "${NR_OCC}" ; replace 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 $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 | StrLen $R3 $4 ;the length of OLD_STR | ||
StrCpy $R4 | StrCpy $R4 0 ;counter initialization | ||
StrCpy $R5 -1 | 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 ;reading 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 searching OLD_STR if no match | ||
StrCpy $8 $7 $5 ;left part | StrCpy $8 $7 $5 ;left part | ||
IntOp $6 $5 + $R3 | IntOp $6 $5 + $R3 | ||
IntCmp $6 0 | IntCmp $6 0 yes no ;left part + OLD_STR == full line read ? | ||
yes: | |||
StrCpy $9 "" | StrCpy $9 "" | ||
Goto done | Goto done | ||
no: | |||
StrCpy $9 $7 "" $6 ;right part | StrCpy $9 $7 "" $6 ;right part | ||
done: | done: | ||
StrCpy $ | 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 4 = $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 5 = $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 counter | |||
Goto | StrCpy $7 $9 ;updating line read 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 lastused | ;Delete $R6 | ||
;SetDetailsPrint lastused | |||
Pop $R6 | Pop $R6 | ||
Pop $R5 | Pop $R5 | ||
Line 145: | Line 188: | ||
Pop $4 | Pop $4 | ||
FunctionEnd | FunctionEnd | ||
== Versions History == | == Versions History == |
Revision as of 20:24, 11 December 2020
Author: Afrow UK (talk, contrib) |
Description
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. Just copy the full code underneath in a file named: ReplaceInFile3.nsh and save it in the Include folder of your NSIS installation folder.
Usage 1
Push hello #text to be replaced Push blah #replace with Push 3 #start replacing after 3rd occurrence Push 4 #replace next 4 occurrences Push C:\temp1.bat #file to replace in Call AdvReplaceInFile
Usage 2
Push hello #text to be replaced Push blah #replace with Push 3 #start replacing after 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:\temp1.bat #file to replace in Call AdvReplaceInFile
/* First occurrence to be replaced: FST_OCC. FST_OCC = all, is the same as FST_OCC = 1.
if FST_OCC greater than the number of occurences: no alteration of the file
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 = 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.
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.
- /
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}" ; start replacing after FST_OCC occurrences Push "${NR_OCC}" ; replace 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 ;reading 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 searching 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 4 = $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 5 = $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 counter StrCpy $7 $9 ;updating line read 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
- 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)