Replace multiple patterns in file using callbacks: Difference between revisions

From NSIS Wiki
Jump to navigationJump to search
m (Updated author links.)
m ("Archive" -> "Wiki". Added link to AdvReplaceInFile.)
 
(2 intermediate revisions by one other user not shown)
Line 1: Line 1:
{|align=right
{{PageAuthor|bazzargh}}
|<small>Author: [[{{ns:2}}:bazzargh|bazzargh]] ([[{{ns:3}}:bazzargh|talk]], [[{{ns:-1}}:Contributions/bazzargh|contrib]])</small>
 
|}
<br style="clear:both;">
== Description ==
== Description ==
There's other versions of find and replace that allow you to find and replace a single string in a file, but they don't deal with multiple replacements on a single line, or replacements of multiple patterns. I've written an alternative that reads and writes a file, calling a supplied function for every line, so you can make that function do the multiple replacements; thus doing all your replacements in a single pass.  
There's other versions of find and replace that allow you to find and replace a single string in a file, but they don't deal with multiple replacements on a single line, or replacements of multiple patterns. I've written an alternative that reads and writes a file, calling a supplied function for every line, so you can make that function do the multiple replacements; thus doing all your replacements in a single pass.  


Its a little faster than doing multiple passes with AdvReplaceInFile, further improvements in find & replace for individual strings will make it faster still.
Its a little faster than doing multiple passes with [[More advanced replace text in file|AdvReplaceInFile]], further improvements in find & replace for individual strings will make it faster still.


== Example Usage ==
== Example Usage ==
Line 25: Line 23:
Push "@@foo@@" ; string to find
Push "@@foo@@" ; string to find
Push "bar" ; string to replace it with
Push "bar" ; string to replace it with
Call StrRep ; see elsewhere in NSIS archive
Call StrRep ; see elsewhere in NSIS Wiki
         ; the string to replace in is at the top of the stack again
         ; the string to replace in is at the top of the stack again
Push "@@tellytubby@@" ; string to find
Push "@@tellytubby@@" ; string to find
Line 79: Line 77:
FunctionEnd
FunctionEnd
</highlight-nsis>
</highlight-nsis>
[[Category:Text Files Manipulation Functions]]

Latest revision as of 21:36, 2 September 2005

Author: bazzargh (talk, contrib)


Description

There's other versions of find and replace that allow you to find and replace a single string in a file, but they don't deal with multiple replacements on a single line, or replacements of multiple patterns. I've written an alternative that reads and writes a file, calling a supplied function for every line, so you can make that function do the multiple replacements; thus doing all your replacements in a single pass.

Its a little faster than doing multiple passes with AdvReplaceInFile, further improvements in find & replace for individual strings will make it faster still.

Example Usage

GetFunctionAddress $R0 ReplaceInSQL ; handle to callback fn
Push $R0
Push "$INSTDIR\template.sql" ; file to replace in
Call ReplaceInFile

Where ReplaceInSQL (or any function of your choosing) looks like:

Function ReplaceInSQL
	; save R1
	Push $R1
	Exch
	; A sequence of replacements.
        ; the string to replace in is at the top of the stack
	Push "@@foo@@" ; string to find
	Push "bar" ; string to replace it with
	Call StrRep ; see elsewhere in NSIS Wiki
        ; the string to replace in is at the top of the stack again
	Push "@@tellytubby@@" ; string to find
	Push "againagain" ; string to replace it with
	Call StrRep 
        ; and so on
	; restore stack
	Exch 
	Pop $R1
FunctionEnd

The Function

Function ReplaceInFile
	Exch $R0 ;file name to search in
	Exch 
	Exch $R4 ;callback function handle
	Push $R1 ;file handle
	Push $R2 ;temp file name
	Push $R3 ;temp file handle
	Push $R5 ;line read
 
	GetTempFileName $R2
  	FileOpen $R1 $R0 r ;file to search in
  	FileOpen $R3 $R2 w ;temp file
 
loop_read:
 	ClearErrors
 	FileRead $R1 $R5 ;read line
 	Push $R5 ; put line on stack
 	Call $R4
 	Pop $R5 ; read line from stack
 	IfErrors exit
 	FileWrite $R3 $R5 ;write modified line
	Goto loop_read
exit:
  	FileClose $R1
  	FileClose $R3
 
   	SetDetailsPrint none
  	Delete $R0
  	Rename $R2 $R0
  	Delete $R2
   	SetDetailsPrint both
 
	; pop in reverse order
	Pop $R5
	Pop $R3
	Pop $R2
	Pop $R1
	Pop $R4
	Pop $R0
FunctionEnd