2

I'm currently running a batch script to search through multiple different files for matching strings. When string A(foobar) matches B+C(foo+bar), then user is prompted to enter D(qux), replacing A with B+D(foo+qux).

During the search, the file will encounter multiple places where the script will replace the same A multiple times, but I don't want to prompt the user every time, only the first encounter.

Attempting at creating a dynamic function, I've supplied my function with 4 different parameters:

B (First part of string): foo

C (Second part of string, getting replaced): bar

X (File location): C:\application.properties

Y (Old stored B+D): fooqux

Y is essentially only supplied as parameter in order for the function to know which variable to overwrite (in my code: batchIp and globalUnitName)

Batch File: How can I have a function return a value when the parameter passed to that function contains spaces? Shows that:

SET %2 = %L%

should be possible.

https://www.dostips.com/DtTutoFunctions.php Shows that:

set "%~1=DosTips"

should be possible.

My code:

:replace_properties
    set batchIp =
    call :replace_string "batch.ip=http://" "192.168.68.132" C:\application.properties %batchIp%
    call :replace_string "batch_ip = " "192.168.68.132" C:\processor.cfg %batchIp%
    set globalUnitName =
    call :replace_string "unit.name=" "Global_Default" C:\application.properties %globalUnitName%

:replace_string
    @echo off
    findstr /m "%~1%~2" %~3 >nul 2>nul
    if %errorlevel%==0 (
        if "%~4"=="" (
            echo File: %~3
            echo   %~1%~2 was found, define new replacement:
            set /p applicationProperty="? %~1"
            IF NOT DEFINED applicationProperty SET "applicationProperty=%~2"
            echo before: %~4
            echo before: %batchIp%
            echo before: %globalUnitName%
            set %~4=!applicationProperty!
            echo after: %~4
            echo after: %batchIp%
            echo after: %globalUnitName%
        ) else (
            set applicationProperty="%~4"
        )
        powershell -Command "(gc %~3) -replace '%~1%~2' , '%~1!applicationProperty!' | Set-Content %~3"
        set applicationProperty=
    )
    exit /B 0

I would expect that the variable batchIp inside :replace_properties would be replaced with the content of applicationProperty inside :replace_string when running set %~4=!applicationProperty!.

However,

echo before: %~4
echo before: %batchIp%
echo before: %globalUnitName%
set %~4=!applicationProperty!
echo after: %~4
echo after: %batchIp%
echo after: %globalUnitName%

turns into:

before:

before:

before:

The syntax of the command is incorrect.

after:

after:

after:

Community
  • 1
  • 1
Gnewbie
  • 21
  • 5
  • 1
    You can't do it this way. `%` variables are created "by value", not "by reference". – montonero Feb 08 '19 at 12:21
  • 1
    No you cannot do that. By setting `set %~1=something` you actually set the variable name of `%~1` and not change the actual value. in other words if I do `set %~1=Test` then `echo %str%` in a batch file and then run `myfile.bat str` it will echo `Test` because we set a variable and value of `str=Test` – Gerhard Feb 08 '19 at 12:22
  • 2
    You need [delayed expansion](http://ss64.com/nt/delayedexpansion.html) when you want to write *and* read variables in the same block of code; otherwise you will get their values *before* the whole block executes. Argument references `%1`etc. cannot be written but read only: if you try to do `set %1=value` you actually set a variable named like the first argument to the value... – aschipfl Feb 08 '19 at 12:24
  • 1
    Please at first read about [delayed expansion](https://stackoverflow.com/a/30284028/2152082) and change your code accordingly. Then describe your remaining issue(s). – Stephan Feb 08 '19 at 12:25
  • An additional issue that I can see is that you should set variables with the format `set "var=value"`. – double-beep Feb 08 '19 at 12:35
  • When plaing spaces around the equal sign in a set command they become part of the variable name and the content. Also called subroutines should be seperated from normal program flow with a prior `Goto :Eof` or `Exit /b` –  Feb 08 '19 at 13:18

0 Answers0