Archive: Find and Replace within a text file


Find and Replace within a text file
Hello,

I am a long time user of NSIS but only have a very superficial knowledge of what goes on under the hood. So please be very specific with what I need to do to get this to work if you can help. I've searched and found similar problems from other users but the answers appear to be more like 'hints' than instructions (I couldn't work them out at all).

I essentially made a graphics mod installer for a game which just writes files into specific locations.

The problem now is that the developer is updating the functionality of the game and adding options to the init file. My script simply replaces the whole init file (thus deleting any new options).

What I want to do is have NSIS search through the existing init file and simply edit the lines with the new graphic options. There is no way of knowing if the line numbers will always be consistent (so I couldn't use LineFind), or if the option defaults will remain the same (so I need to be able to search using wildcards or partial lines).

For example, I need to search through the file until it finds a line starting with:

[GraphicOption:

and then replace the whole line with:

[GraphicOption: NewGraphicSet]

I really hope someone can help me with this. I've looked at LineFind etc but I can't work them out.


Here you are,

!macro ReplaceStrFunc UN
Function ${UN}ReplaceStr
Exch $0
Exch
Exch $1
Exch
Exch 2
Exch $2
Push $3
Push $4
Push $5
Push $6

StrCpy $4 "0"
StrLen $5 "$1"
StrLen $6 "$2"
IntCmp $5 $6 0 0 _err
Intop $6 $6 - $5

_start:
StrCpy $3 "$2" $5 $4
StrCmp "$3" "$1" _next
IntCmp "$4" "$6" _err
Intop $4 $4 + 1
Goto _start

_next:
Intop $5 $5 + $4
StrCpy $3 "$2" "$4"
Push $3
StrCpy $3 "$2" "" "$5"
Push $3
Pop $5
Pop $4
StrCpy $0 "$4$0$5"
Goto _done

_err:
StrCpy $0 "error"

_done:
Pop $6
Pop $5
Pop $4
Pop $3
Pop $2
Pop $1
Exch $0
FunctionEnd
!macroend

!macro ReplaceStrCall _UN _INPUT _FIND _REPLACE _RESULT
Push "${_INPUT}"
Push "${_FIND}"
Push "${_REPLACE}"
Call ${_UN}ReplaceStr
Pop "${_RESULT}"
!macroend

!macro FindRepStr
!define FindRepStr `!insertmacro ReplaceStrCall ""`
!insertmacro ReplaceStrFunc ""
!macroend

!macro un.FindRepStr
!define un.FindRepStr `!insertmacro ReplaceStrCall "un."`
!insertmacro ReplaceStrFunc "un."
!macroend


;----------------------------------------
; Example of usage

outfile 'test.exe'

!define STRTOFIND "[GraphicOption:"
!define STRTOREPL "[GraphicOption: NewGraphicSet]"

!insertmacro FindRepStr
;!insertmacro un.FindRepStr

Section "Usage Example"
FileOpen $0 "path_to_file_to_be_replaced" r
FileOpen $1 "$EXEDIR\example.txt" w
loop:
FileRead $0 $2
IfErrors done
${FindRepStr} "$2" "${STRTOFIND}" "${STRTOREPL}" "$R0"
StrCmp $R0 "error" 0 +3
FileWrite $1 "$2"
goto loop
FileWrite $1 "$R0"
goto loop
done:
FileClose $0
FileClose $1

ExecShell open "$EXEDIR\example.txt"
SectionEnd

Thanks for your reply Red Wine.

I've tried to test the script but I am getting a compile error. I placed the macros at the end of the script with the page functions but the compiler is not recognizing them.

I was also unsure if this script will completely replace the line of code, or just the searched text. It is important that the whole line be replaced.

Thanks


Name "Test"
OutFile "Test.exe"

!include "TextFunc.nsh"
!insertmacro LineFind

!define STRTOFIND "[GraphicOption:"
!define STRTOREPL "[GraphicOption: NewGraphicSet]"

Section
${LineFind} "C:\Input.txt" "C:\Output.txt" "1:-1" "LineFindCallback"

IfErrors 0 +2
MessageBox MB_OK "Error"
SectionEnd

Function LineFindCallback
StrLen $0 "${STRTOFIND}"
StrCpy $1 "$R9" $0
StrCmp $1 "${STRTOFIND}" 0 End
StrCpy $R9 "${STRTOREPL}$\r$\n"

End:
Push $0
FunctionEnd

Originally posted by Das123
Thanks for your reply Red Wine.

I've tried to test the script but I am getting a compile error. I placed the macros at the end of the script with the page functions but the compiler is not recognizing them.

I was also unsure if this script will completely replace the line of code, or just the searched text. It is important that the whole line be replaced.

Thanks
You should add the macro on the top of your code, same way like the provided example.
Simply compile the provided example and watch the result if it satisfies you.

Originally posted by Red Wine
You should add the macro on the top of your code, same way like the provided example.
Simply compile the provided example and watch the result if it satisfies you.
Thanks for the replies Red Wine and Instructor.

I got the script to compile, Red Wine, but it still doesn't replace the whole line. It only replaces the searched text.

I'll try Instructor's script and report back.

Thanks again

Success!!

Thanks Instructor. This works perfectly.

One more question. How do I hide the process from the user? Is there a command to not show the section when it executes?