Batch: Replacing a line by another line

2019-07-16 03:57发布

问题:

I know similar questions had been asked many time, but I cannot workout something fitting my needs...

So I have a file, containing a secret key, the line is starting like :

SECRET_KEY = 

The secret key is a non-fixed length.

I want to find this line, to save it somewhere, to replace the all file containing the secret key by another file (very similar, but with a different secret key which I don't want), and to reintroduce the original secret key in the new file!

So for the moment I have this code:

echo Saving the actual SECRET_KEY...
findstr "SECRET_KEY" somefile.py > SECRET_KEY.txt
echo Copying source code files...
xcopy %~dp0\somepath %~dp0\someotherpath /EY

This part is working, as I have stored the original secret key in a text file, and replaced the file by another (together with other files, directories structures, etc...)

So now how can I find again the line starting by SECRET_KEY and replace the all line by the content of SECRET_KEY.txt?

EDIT: I made some progress I think:

echo Saving the SECRET_KEY...
findstr "SECRET_KEY" inputfile.py > SECRET_KEY.txt

echo Copying source code files...
xcopy %~dp0\somepath %~dp0\someotherpath /EY

echo Restoring the SECRET_KEY...
setlocal EnableDelayedExpansion
for /F "delims=" %%a in ('findstr /I "SECRET_KEY" SECRET_KEY.txt') do set "secret_key=%%a"
echo !secret_key!
@echo off
set file=inputfile.py
set newline=!secret_key!
set insertline=23
set output=outputfile.py
(for /f "tokens=1* delims=[]" %%a in ('find /n /v "##" ^< "%file%"') do (
if "%%~a"=="%insertline%" (
echo !newline!
) ELSE (
echo.%%b
)
)) > %output%

I can then delete SECRET_KEY.TXT, inputfile.py, and rename outputfile.py into inputfile.py Most likely not the most efficent way, but it works...

EXCEPT for one thing! I have a lot a special characters in this inputfile, that's why I used !secret_key! for example...

But I also have a lot of:

[some stuff]

and in the outputfile, it appears as:

[some stuff

So I guess I'm close, but I can't find a delimiter which will allow every single character to be outputed!

回答1:

The following script reads the line containing SECRET_KEY from file otherfile.py at first; then it gets the number of the line of the input file inputfile.py where SECRET_KEY is placed; afterwards it reads the file inputfile.py line by line, check each line number whether it matches the previously found one; if a match is found, the previously gathered key from file otherfile.py is returned, so the line is replaced; otherwise, the line returned unedited; the output data is written to file outputfile.py:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "INFILE=inputfile.py"
set "OUTFILE=outputfile.py"
set "KEYFILE=otherfile.py"
set "KEYWORD=SECRET_KEY"

rem // Retrieve key from a file:
set "KEY="
setlocal EnableDelayedExpansion
for /F delims^=^ eol^= %%K in ('findstr /L /C:"!KEYWORD!" "%KEYFILE%"') do (
    endlocal
    set "KEY=%%K"
    rem // Toggle delayed expansion inside of the loop to not lose `!`:
    setlocal EnableDelayedExpansion
    rem // `goto` ensures to take *first* key; remove it to take *last* one;
    goto :CONT_KEY
)
:CONT_KEY
endlocal

rem // Retrieve line number where key is found:
set "LRPL="
setlocal EnableDelayedExpansion
for /F "delims=:" %%M in ('findstr /N /L /C:"!KEYWORD!" "%INFILE%"') do (
    endlocal
    set "LRPL=%%M"
    rem // Toggle delayed expansion inside of the loop to not lose `!`:
    setlocal EnableDelayedExpansion
    rem // `goto` ensures to take *first* key; remove it to take *last* one;
    goto :CONT_NUM
)
:CONT_NUM
endlocal

rem // Move line by line from one file to another and replace key:
> "%OUTFILE%" (
    rem /* Use `findstr` to precede every line with its line number plus `:`,
    rem    in order no line to appear empty to `for /F`, as this ignores such;
    rem    the prefix (up to and including the first `:`) is removed later: */
    for /F "delims=" %%L in ('findstr /N /R "^" "%INFILE%"') do (
        set "LINE=%%L"
        rem // Extract the prefixed number of the current line:
        for /F "delims=:" %%N in ("%%L") do set "LNUM=%%N"
        rem // Toggle delayed expansion inside of the loop to not lose `!`:
        setlocal EnableDelayedExpansion
        rem /* Check current line number against previously retrieved one
        rem    and replace line in case of a match: *//
        if !LNUM! EQU !LRPL! (echo(!KEY!) else (echo(!LINE:*:=!)
        endlocal
    )
)

endlocal
exit /B

Note that the KEYFILE and INFILE variables (defined at the top of the script) may be set to the same file path. However, OUTFILE must be different from INFILE; otherwise the referred file will be emptied.

This covers only the tasks of storing the SECRET_KEY line of a file to a variable and of exchanging the line containing SECRET_KEY in a file by the previously stored one and write the result to another file.