I want to be able to replace a line in a properties file but i only know part of the line string at any one time
Heres the line i want to replace: mb.datasource.password=ENC(8dF45fdD)
with this: mb.datasource.password=apassword
What i have just now is this
#echo off &setlocal
set "search=mb.datasource.password="
set "replace=mb.datasource.password=apassword"
set "textfile=mb.properties"
set "newfile=mb-new.properties"
(for /f "delims=" %%i in (%textfile%) do (
set "line=%%i"
setlocal enabledelayedexpansion
set "line=!line:%search%=%replace%!"
echo(!line!
endlocal
))>"%newfile%"
This ends up giving me mb.datasource.password=apassword=ENC(8fFdeUdK)
I can't just find the full string it needs to only be mb.datasource.password= because the part after the equals changes
Any help would be greatly appreciated?
You can do it with batch. I put together a quick script and it worked for me:
#ECHO OFF
SETLOCAL EnableExtensions
SET SourceFile="mb.properties"
SET OutputFile="mb-new.properties"
SET "FindKey=mb.datasource.password"
SET "NewValue=apassword"
REM Basic parse for INI file format.
(FOR /F "usebackq eol= tokens=1,* delims==" %%A IN (`TYPE %SourceFile%`) DO (
REM If the key value matches, build the line with the new value.
REM Otherwise write out the existing value.
IF /I "%%A"=="%FindKey%" (
ECHO %%A=%NewValue%
) ELSE (
ECHO %%A=%%B
)
)) > %OutputFile%
REM Replace old with new.
DEL %SourceFile%
MOVE %OutputFile% %SourceFile%
ENDLOCAL
A few notes about the above:
I assumed basic INI file format.
The FOR loop will skip blank lines so they would be removed from the new output file. There are ways around this using tricks with the FIND command if the blanks are needed.
If you have special chars (% or ! especially) - this may cause some problems, but if you have just "normal" text then it should be fine.
Related
I have an input text file with some server names
I am trying to replace the 'new line' for each server with |.
abcdef.abcdef.abcdef
testing
example
When executed in cmd.exe my script doesn't parse all lines from the input file. Say, if I have 1000 servers in my input file, I can see the output in the Command Prompt window for just around 500 servers.
#echo off
setlocal enableextensions
SETLOCAL EnableDelayedExpansion
rem Purpose - To remove domain name of servers and convert line by line strings to | seperated strings.
type nul > Del_Output.txt
for /f "tokens=1 delims=." %%a in (Downtime.txt) do (
echo(%%a>> Del_Output.txt
)
type Del_Output.txt
rem Initialize the output line
set "line="
rem Catenate all file lines in the same variable separated by "|"
for /F "delims=" %%a in (Del_Output.txt) do set "line=!line!|%%a"
rem Show final line, removing the leading "|"
rem echo !line:~1!>FinalOutput.txt
echo !line:~1!
rem type "C:\Users\AAithal\Desktop\MoogSoft_Downtime\FinalOutput.txt"
ENDLOCAL
Some pointers on the issue would be very helpful.
This should work:
#echo off
setlocal
set "first="
< nul (
for /F "delims=." %%a in (Downtime.txt) do (
if not defined first (
set "first=1"
set /P "=%%a"
) else (
set /P "=|%%a"
)
)
echo/
) > Output.txt
As others have indicated already, the maximum length of a batch variable is 8192 characters, so all names that exceed such a size are not included in your code...
The solution is not use a variable to collect the output. The set /P command allows to output a string with no LF at end, so the input lines are just joined in a long output line.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q56905805.txt"
SET "outline="
FOR /f "usebackqdelims=" %%a IN ("%filename1%") DO (
FOR /f "tokens=1*delims=." %%i IN ("%%a") DO IF "%%j"=="" (
SET "outline=!outline!|%%a"
) ELSE (
IF DEFINED outline ECHO !outline!
SET "outline=%%i"
)
)
IF DEFINED outline ECHO !outline!
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances. The listing uses a setting that suits my system.
I used a file named q56905805.txt containing your data for my testing.
The usebackq option is only required because I chose to add quotes around the source filename.
Assign each line to %%a, then reparse it with the delimiter. It it contains the delimiter, it's a new server, so output the previous one and start anew, else accumulate with the required separator.
I'm trying to extract every value for FileRef from a string I've already extracted out of a file. Unfortunately, the string is one line which makes it more difficult to use for /f "tokens=*".
The string is:
"<Cim:TrnTable_list><Cim:TrnTable Id="Root"><Cim:TrnElem Ref="3" FileRef="A1-FS.elt"/><Cim:TrnElem Ref="4" FileRef="A1-MS.elt"/><Cim:TrnElem Ref="9" FileRef="Product\Product-v1\Product-v1-MD.elt"/><Cim:TrnElem Ref="11" FileRef="Product\Product-v2\Product-v2-MD.elt"/><Cim:TrnElem Ref="12" FileRef="RunnerPart_Assembly#1.elt"/></Cim:TrnTable></Cim:TrnTable_list>"
How to get every value for FileRef inserted into a variable in the following format?:
A1-FS.elt?A1-MS.elt?Product\Product-v1\Product-v1-MD.elt?Product\Product-v2\Product-v2-MD.elt?RunnerPart_Assembly#1.elt
I mean, then I could loop trough them using for /f "delims=?" right?
Or is there a way to convert each ? in the above example to a 'new line' within one string, or maybe even better ideas to loop trough each FileRef-value?
Many thanks!
Squashman is right in his comment, use a language that is capable of handling XML data natively.
Anyway, if you insist on using pure Windows batch scripting, you could assemble a new string with ? symbols as separator like in the following script:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_FILE=%~dpn0.txt" & rem // (path to file containing the line of text)
(set ^"_LF=^
%= empty line =%
^") & rem // (this constitutes a new-line character)
rem // Initialise collection variable:
set "COLL=?"
rem // Read line from file:
for /F "usebackq delims=" %%L in ("%_FILE%") do (
set "LINE=%%~L"
setlocal EnableDelayedExpansion
rem // Replace `><` by `>` + line-break + `<`:
set ^"LINE=!LINE:^>^<=^>^%_LF%%_LF%^<!^"
rem // Read one tag enclosed within `<` and `>`:
for /F "delims=" %%I in ("!LINE!") do (
endlocal
set "ITEM=%%I"
rem // Extract string between ` FileRef` and `/>`:
setlocal EnableDelayedExpansion
set "ITEM=!ITEM:* FileRef=!"
set "ITEM=!ITEM:/>=!"
rem // Check for `=`-sign after `FileRef`:
if "!ITEM:~,1!"=="=" (
rem // Remove leading `=` and surrounding `""`:
for /F "delims=| eol=|" %%F in ("!ITEM:~1!") do (
endlocal
set "NAME=%%~F"
rem // Assemble return string using `?` as separator:
setlocal EnableDelayedExpansion
for /F "delims=| eol=|" %%J in ("!COLL!!NAME!?") do (
endlocal
set "COLL=%%J"
setlocal EnableDelayedExpansion
)
)
)
)
endlocal
)
rem // Return collection variable:
setlocal EnableDelayedExpansion
echo(!COLL:~1,-1!
endlocal
endlocal
exit /B
Toggling delayed expansion is done in order not to have trouble with ! symbols.
Better than collecting all values in a single variable is to just loop through them in my opinion.
This is one other way to brute force this. This code will put each FileRef into its own variable and sequence the variable name up.
#echo off
FOR /F "delims=" %%G IN (line.txt) do set "line=%%G"
set i=0
:loop
set /a i+=1
set "line=%line:*FileRef=%"
FOR /F "tokens=1* delims==/" %%G IN ("%line%") DO (
set "var%i%=%%~G"
set "line=%%H"
)
echo "%line%"|find /I "fileref" >nul 2>&1 &&GOTO loop
set var
pause
When executed it will output this.
C:\BatchFiles\SO\XML>bruteforce.bat
var1=A1-FS.elt
var2=A1-MS.elt
var3=Product\Product-v1\Product-v1-MD.elt
var4=Product\Product-v2\Product-v2-MD.elt
var5=RunnerPart_Assembly#1.elt
Press any key to continue . . .
If you don't want the data assigned into their own individual variables you can just use the %%G meta-variable directly inside the FOR command.
I'm working on a DOS script in order to search a line and replace it into files from a specific folder. Here is what i have already done :
#echo off
setlocal enableextensions disabledelayedexpansion
set "search=#Interceptors({ RuntimeExceptionInterceptor.class }^)"
set "replace=#Interceptors({ RuntimeExceptionInterceptor.class, ReportInterceptor.class, CorrelationIdInterceptor }^)"
set "textFile=C:\Utilisateurs\a669884\Documents\test.txt"
for %%a in (*.txt) do (
echo "%%a"
for /f "Delims=" %%i in (%%a ^& break ^> %%a) do (
set "line=%%i "
setlocal enabledelayedexpansion
>>%%a echo(!line:%search%=%replace%!
endlocal
)
)
Problem is that my first line is not replace by the new one, the new line is added under it like that :
#Interceptors({ RuntimeExceptionInterceptor.class })
#Interceptors({ RuntimeExceptionInterceptor.class, ReportInterceptor.class, CorrelationIdInterceptor })
Do you know why my first line isn't replaced? Thanks a lot
Seb
Not sure what setting textfile has to do with the routine - it's not used.
Your original code produced a complaint that & was not found and created an empty file for me.
Changing the for to
for /f "Delims=" %%i in ('type "%%a" ^& break ^> "%%a"') do (
seemed to make the substitution, given the one line (partial?) of sourcefile you've provided, plus a few dummy lines.
execute the type... with the filenames enclosed in quotes to ensure correct operation with separators, replacing the file; substitute as specified.
I am capturing a m3U file on a daily basis but wish to parse part of it to another file with the few channels I need.
For example I have renamed my m3U to Test.txt file which say has the following fictional structure:
#EXTINF:0,ABC
#live link 1
#EXTINF:0,XYZ
#live link 2
#EXTINF:0,UVW
#live link 3
I would just like to capture say the line staring from "#EXTINF:0,XYZ" and say the line beneath it to end up with a Output.txt as follows:
#EXTINF:0,XYZ
#live link 2
I know that one needs to use the For loop but I am a bit of a noob on this area.
Put this code into the file filter.cmd.
#echo off
set INPUT=%1&set MATCH=%2& set MATCHED=0
for /f "delims=" %%a in (%INPUT%) do call :line "%%~a"
goto :eof
:line
set EXT=&TITLE=&
for /f "tokens=1 delims=:" %%a in ("%~1") do set EXT=%%~a
for /f "tokens=1,2,* delims=:," %%a in ("%~1") do set TITLE=%%~c
if "%EXT%" == "#EXTM3U" echo %~1
if "%EXT%" == "#EXTINF" (
set MATCHED=0
echo %TITLE%| findstr /l %MATCH% >nul && set MATCHED=1
)
if %MATCHED%==1 echo %~1
Use example:
filter.cmd input_file.m3u XYZ > output_file.m3u
Here is some explanation:
Every input line is split using for /f with tokens and delims.
MATCHED is set if the line begins with #EXTINF and the rest contains the string to match (second argument).
if MATCHED is set, the lines are output until next #EXTINF.
I would do it like this, supposing the .m3u file does not contain trailing white-spaces in the lines preceded by #EXTINF, like your sample data does:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "FILE=%~1"
set "HEADER=#EXTM3U"
set "PREFIX=#EXTINF"
set "MATCH=%~2"
set "FLAG="
for /F usebackq^ delims^=^ eol^= %%L in ("%FILE%") do (
if defined FLAG (
echo(%%L
set "FLAG="
)
for /F "delims=:" %%P in ("%%L") do (
if "%%P"=="%HEADER%" (
echo(%%L
) else if "%%P"=="%PREFIX%" (
set "LINE=%%L"
setlocal EnableDelayedExpansion
if /I "!LINE:*,=!"=="!MATCH!" (
echo(!LINE!
endlocal
set "FLAG=#"
) else endlocal
)
)
)
endlocal
exit /B
Call the script like this, supposing it is saved as extract-entry.bat:
extract-entry.bat "input_file.m3u" "XYZ" > "output_file.m3u"
The script walks through the given .m3u file line by line. It returns the current line unedited and resets variable FLAG, if variable FLAG is set, which is not the case at the beginning.
Then it looks for #EXTINF. If found (e. g., #EXTINF:0,XYZ), the string after the comma (XYZ) is compared against the given search string. If matched, the current line is output and FLAG variable is set now in order to get the following line too.
The header line #EXTM3U is always output.
Toggling delayed expansion makes this script robust against all characters that have special meaning to the command interpreter without losing them.
#echo off
setlocal enableextensions disabledelayedexpansion
for /r %f in (xis_a*) do More +1 %~nxf >> No_header_%~nxf
set "search=:20:"
set "replace={:20:"
for /f "delims=" %%i in ('type (No_header_*.txt) ^& break ^> (No_header_*.txt) ') do (
set "line=%%i"
setlocal enabledelayedexpansion
set "line=!line:%search%=%replace%!"
>>No_header_*.txt echo(!line!
endlocal
)
am trying to skip the header line in a text file and replace :20: with {:20:. i have written and have achieved almost.. please try to help me am totally new to this
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
set "search=:20:"
set "replace={:20:"
for /r "%sourcedir%" %%f in (xis_a*) do (
REM DEL "%destdir%\No_header_%%~nf.txt" >NUL 2>nul
for /f "usebackqskip=1delims=" %%i in ("%%f") do (
set "line=%%i"
setlocal enabledelayedexpansion
set "line=!line:%search%=%replace%!"
>>"%destdir%\No_header_%%~nf.txt" echo(!line!
ENDLOCAL
)
)
GOTO :EOF
This should solve the problem.
In your code, the initial setlocal is establishing the default condition, so I omitted it.
You have %f in your 'for /r - the % before the metavariable f needs to be doubled.
The more ceremony isn't required - for /f has a skip option which will allow the first n lines to be skipped.
So - all that is required is to get the list of files generated by the for...%%f... loop and with each, process each individual file, skipping the first line. Quoting the filename appearing in %%f is simply a safety-measure to allow for filenames containing separators, but this means that usebackq needs to be invoked to tell for /f that the list given is not a literal string (which it will assume for a "quoted string,") but a filename.
Then, since %%f is in-context for the %%i loop, you can select the target filename by using %%~nf. I'm not sure whether you want ~nf or ~nxf (adding a second .txt extension) so I elected to use ~n alone. Note that your use of * is doomed - that means "all files matching" - probably not quite what you want, and cmd will get very confused.
I've aded a remmed-out del command to allow the destination file to be deleted - just remove the rem if required, otherwise the data will be appended to any exiating file.
I use my u: drive for testing, and have left my source and destination names in place. No doubt you would need to change those to suit your system.