0

I'm trying to replace some text in a .yml file using batch.

My code:

@echo off
if not defined in_subprocess (cmd /k set in_subprocess=y ^& %0 %*) & exit )
setlocal enableextensions 

set jruby="%~dp0jruby\bin\jruby"
set someDir="%~dp0..\test\test2"

cd %someDir%
copy /y file.yml test_file.yml > NUL
for /f "tokens=2*" %%i in (file.yml) do @set "password=%%i"
echo Your password --- %password% --- will now be encrypted due to security reasons...

%jruby% -S run_file.rb 

for /f "delims=" %%x in (some_file.rb) do set some_key=%%x

FOR /F "tokens=* USEBACKQ" %%F IN (`%jruby% -S encrypt_property_for_yaml encrypt %some_key% %password%`) DO (
SET encrypted_pw=%%F
)
echo Random 32-Bit encryption key created: %some_key%
echo Password was encrypted to: %encrypted_pw%
echo.
echo Encrypted password will be saved in file.yml file...

set "replace=%encrypted_pw%"
set "databaseFile=file.yml"
set "search=%password%"

for /f "delims=" %%i in ('type "%databaseFile%" ^& break ^> "%databaseFile%" ') do (
    set "line=%%i"
    setlocal enabledelayedexpansion
    >>"%databaseFile%" echo(!line:%search%=%replace%!
    endlocal
)
pause

The error occurs due to this code block

set "replace=%encrypted_pw%"
set "databaseFile=file.yml"
set "search=%password%"

for /f "delims=" %%i in ('type "%databaseFile%" ^& break ^> "%databaseFile%" ') do (
    set "line=%%i"
    setlocal enabledelayedexpansion
    >>"%databaseFile%" echo(!line:%search%=%replace%!
    endlocal
)
pause

The whole thing works perfectly, but as soon as I reach the last FOR-BLOCK where the actual replace takes place, I always get the following error:

! was unexpected at this time

At first I thought it was due to the missing closing bracket on echo, but that still causes the same error.

*Side note: the method I use to find and replace was originally from here

The funny thing is, when I run the same code in a completely separate .bat file, it works flawlessly, but when I use it with the current batch file including other code, I always get the same error. I tried using set instead of >>"%databaseFile%" echo(!line:%search%=%replace%!

I tried googling, found some similar situations where it has something to do with the delayedexpansion but I can't seem to get the FIND and REPLACE to work.

Pro_grammer
  • 346
  • 2
  • 9
  • Show my an example of an _"encrypted password"_ as defined in your examples. – Gerhard Dec 03 '21 at 10:41
  • @Gerhard something like this: ENC(qQU35msnA699PH9RX18XYQ==) and i checked with echo off, it gets assigned to variable properly – Pro_grammer Dec 03 '21 at 10:43
  • 1
    There's you problem. You need to escape the closing parenthesis as `^)` The code block is seeing it as a closing parenthesis for itself. – Gerhard Dec 03 '21 at 10:44
  • @Gerhard you mean the closing parenthesis on the ENC(qQU35msnA699PH9RX18XYQ==) ? I assign it at SET encrypted_pw=%%F, do i add the ^) after the %%F? – Pro_grammer Dec 03 '21 at 10:46
  • No. the solution will depend on the following. is the password in double quotes in the file? – Gerhard Dec 03 '21 at 10:57
  • @Gerhard yeah its written in a file in the directory im in. Its in the file.yml and i save the password content into the variable %password% – Pro_grammer Dec 03 '21 at 11:00
  • yes, but is the password double quoted in the `yml` file or not. i.e `pass="ENC(qQU35msnA699PH9RX18XYQ==)"` or without `pass=ENC(qQU35msnA699PH9RX18XYQ==)` – Gerhard Dec 03 '21 at 11:02
  • oh im sorry misunderstood, no its without " " @Gerhard – Pro_grammer Dec 03 '21 at 11:02
  • 1
    ok, so directly before `set "replace=%encrypted_pw%"` do `set "encrypted_pw=%encrypted_pw:)=^)%"` I must also warn you, should your password contain `!` it will remove it due to `delayedexpansion` so do consider that as well. There are ways around that though. – Gerhard Dec 03 '21 at 11:30
  • I’ll give it a go and if it works, I’d appreciate it if you post it as an answer so I can upvote and accept as solution :) @gerhard – Pro_grammer Dec 03 '21 at 11:37

1 Answers1

1

The passwords contains closing parathesis which is seen as a closure of the code block. You need to escape the occurrence of each )

In the below code snipped, I added the replacement section:

set "encrypted_pw=%encrypted_pw:)=^)%"
set "replace=%encrypted_pw%"
set "databaseFile=file.yml"
set "search=%password%"

for /f "delims=" %%i in ('type "%databaseFile%" ^& break ^> "%databaseFile%" ') do (
    set "line=%%i"
    setlocal enabledelayedexpansion
    >>"%databaseFile%" echo(!line:%search%=%replace%!
    endlocal
)
pause

Alterantively, and even better you can make it even shorter and let it be part of the replacement itself in the loop:

set "replace=%encrypted_pw%"
set "databaseFile=file.yml"
set "search=%password%"

for /f "delims=" %%i in ('type "%databaseFile%" ^& break ^> "%databaseFile%" ') do (
    set "line=%%i"
    setlocal enabledelayedexpansion
    >>"%databaseFile%" echo(!line:%search%=%replace:)=^)%!
    endlocal
)
pause

EDIT: to retain open lines.

@echo off
set "search=word to search"
set "replace=to replace"
set "databaseFile=file.yml"

for /f "delims=" %%i in ('type "%databaseFile%" ^| find /n /v "^"  ^& break ^> "%databaseFile%" ') do (
    set "line=%%i"
    setlocal enabledelayedexpansion
    set "line=!line:*]=!"
    >>"%databaseFile%" echo(!line:%search%=%replace%!
    endlocal
)
pause
Gerhard
  • 22,678
  • 7
  • 27
  • 43