Extract only specific string using windows batch script - batch-file

Using Windows Batch script, I need the output as shown below. Please help.
Input:
APP "Default Web Site/" (applicationPool:DefaultAppPool)
APP "Default Web Site/App1" (applicationPool:App1)
APP "Default Web Site/App1/Pages" (applicationPool:App1)
App "Site1/App2/" (applicationPool:App2)
App "Site1/App3/VD1" (applicationPool:VD1)
Output:
Default Web Site
Site1

This works with the sample data.
#echo off
(for /f "delims=/" %%a in (file.txt) do (
for /f "tokens=1,*" %%b in ("%%~a") do (
echo %%~c
)
))>temp.fil
sort <temp.fil |uniq
del temp.fil
pause
The code below is uniq.bat
Place uniq.bat in the same folder as the batch file above or in a directory on the path.
#if (#CodeSection == #Batch) #then
#CScript //nologo //E:JScript "%~F0" & goto :EOF & Rem aacini 2013
#end
var line, prevLine = "";
while ( ! WScript.Stdin.AtEndOfStream ) {
line = WScript.Stdin.ReadLine();
if ( line != prevLine ) {
WScript.Stdout.WriteLine(line);
prevLine = line;
}
}

#echo off
setlocal
set "arg_two=%~2"
for /f "tokens=1 delims=/" %%a in ("%arg_two%") do echo %%a
endlocal
test:
outputparser.bat APP "Default Web Site/" (applicationPool:DefaultAppPool)
>Default Web Site
outputparser.bat App "Site1/App3/VD1" (applicationPool:VD1)
>Site1
But if you set quotes around the input it will not work.
EDIT with a file to process (content is the same as in the question):
#echo off
setlocal
set "file_to_process=.\input_file.txt"
for /f "usebackq tokens=1 delims=(" %%W in ("%file_to_process%") do (
for /f usebackq^ tokens^=2^ delims^=/^" %%a in ('%%~W') do (
echo %%a
)
)
endlocal

#echo off
setlocal enableextensions enabledelayedexpansion
set "inputFile=c:\somewhere\file.dat"
rem Extract the required part of the lines
set "tempFile=%temp%\%~nx0.%random%.tmp"
> "%tempFile%" (
for /f usebackq^ tokens^=2^ delims^=^/^" %%a in ("file.txt") do (echo(%%a)
)
rem Remove the duplicates from the list
set "previous="
for /f "tokens=*" %%f in ('type "%tempFile%" ^| sort') do (
if not "%%f"=="!previous!" (
echo(%%f
set "previous=%%f"
)
)
rem Cleanup
del "%tempFile%" >nul 2>nul
endlocal
It uses the quotes and slashes as delimiters to cut the lines on the required points. Then the list is sorted to eliminate duplicates from the output

#echo off
setlocal enableDelayedExpansion
set "val="
for /f tokens^=2^ delims^=/^" %%A in ('sort input.txt') do (
if "!val!" neq "%%A" echo %%A
set "val=%%A"
)
In the unlikely event that a value may contain !, then you would need
#echo off
setlocal disableDelayedExpansion
set "val="
for /f tokens^=2^ delims^=/^" %%A in ('sort input.txt') do (
set "new=%%A"
setlocal enableDelayedExpansion
if "!val!" neq "!new!" echo !new!
endlocal
set "val=%%A"
)

Related

find and replace a string in xml using batch

Sample input:
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;NEWCODE;% (PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
Intended output:
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_LARGE_;WIN32;_WINDOWS;_DEBUG;NEWCODE;% (PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
Current output when running batch multiple times:
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_LARGE;_LARGE_;WIN32;_WINDOWS;_DEBUG;NEWCODE;% (PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
Batch file:
#echo off
setlocal enableextensions enabledelayedexpansion
set "textFile="C:\"
set "file2=%textFile%\sample.vcxproj"
set list=%file2%
set "WIN32=^<PreprocessorDefinitions^>"
set "LARGE_=_LARGE_;"
set "replace=%WIN32%_LARGE_;"
set "cmd=%1"
set "append=enable"
set "remove=disable"
set "empty="
echo %replace% !WIN32!
(for %%a in (%list%) do (
IF "%cmd%"=="%remove%" (
echo removed
for /f "delims=" %%i in ('type %%a ^& break ^> %%a ') do (
set "line=%%i"
setlocal enabledelayedexpansion
>>"%%a" echo(!line:%LARGE_DICOM%=%empty%!
endlocal
)
)
IF "%cmd%"=="%append%" (
echo append
echo %%a
for /f "delims=" %%i in ('type %%a ^& break ^> %%a ') do (
set "line=%%i"
Echo "%%i" |findstr /R "%replace%" 1>nul
if %errorlevel%==0 (
echo eexist
)
setlocal enabledelayedexpansion
>>"%%a" echo(!line:%WIN32%=%replace%!
endlocal
)
)
echo %%a
))
I am trying to find LARGE in preprocessor, if not exist add it, but it is adding multiple times
Find and, search is not working. I need to append only if it not exist.
Append to file if particular sting not found, string should append once, even if we run batch multiple times.

Add numbers with same text together

I would like to create a batch file in which I can see what I have collected in a game.
The game saves this information in a .txt file.
The output would look like this.
70x Silver.
Back Pearl.
41x Copper.
Amethyst.
Amethyst.
12x Silver.
Back Pearl.
21x Copper.
5x Silver.
Back Pearl.
Back Pearl.
Amethyst.
What I want to do now, is to add the items with the same name together, like this:
128x Silver.
4x Back Pearl.
62x Copper.
3x Amethyst.
There are hundreds of items with different names, not just these 4.
Would that be possible?
Any help would be appreciated. Thanks!
Another one!
#echo off
setlocal EnableDelayedExpansion
for /F "delims=" %%l in (test.txt) do for /F "tokens=1*" %%a in ("%%l") do (
set "first=%%a"
if "!first:~-1!" equ "x" (set /A "num=!first:~0,-1!") else set "num=0"
if !num! equ 0 (
set "rest=%%l"
set /A "count[!rest: =_!]+=1"
) else (
set "rest=%%b"
set /A "count[!rest: =_!]+=num"
)
)
(for /F "tokens=2* delims=[]=" %%a in ('set count[') do (
set "item=%%a"
if %%b equ 1 (
echo !item:_= !
) else (
echo %%bx !item:_= !
)
)) > summary.txt
#ECHO OFF
SETLOCAL
rem The following settings for the source directory and filename are names
rem that I use for testing and deliberately include names which include spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.
SET "sourcedir=u:\your files"
SET "filename1=%sourcedir%\q72672485.txt"
:: remove variables starting #
FOR /F "delims==" %%b In ('set # 2^>Nul') DO SET "%%b="
FOR /f "usebackqdelims=" %%b IN ("%filename1%") DO (
CALL :sub %%b
)
SETLOCAL ENABLEDELAYEDEXPANSION
(
FOR /F "tokens=1,2delims==" %%b In ('set # 2^>Nul') DO (
SET "line=%%cx%%b"
ECHO !line:#= !
)
)>summary.txt
endlocal
type summary.txt
GOTO :EOF
:sub
SET "quantity=%1"
SET "line=%*"
IF /i "%quantity:~-1%"=="x" (SET /a quantity=%quantity:~0,-1%&SET "line=%line:* =%") ELSE SET quantity=1
IF %quantity%==0 SET /a quantity=1&SET "line=%*"
SET /a #%line: =#%+=quantity
GOTO :eof
Different approach...
Would that be possible? - Yes.
#echo off
setlocal enabledelayedexpansion
for /f "delims=" %%a in (t.txt) do (
set " z=%%a"
set " z=!z:x =#!"
set " z=!z: =_!"
for /f "tokens=1,2 delims=#" %%b in ("!z!") do (
if "%%c" == "" (
set "x=1"
set "y=%%b
) else (
set "x=%%b"
set "y=%%c"
)
set /a #!y!+=!x!
)
)
(for /f "tokens=1,2 delims=#=" %%a in ('set #') do (
set "x=%%a"
set "y=%%bx "
echo !y:~0,4! !x:_= !
))>summary.txt
Output with your example data (I hope, alphabetic sorting is ok for you):
3x Amethyst.
4x Back Pearl.
62x Copper.
87x Silver.
(your calculation of 120 silver might be a bit optimistic with the given input data)
This is a different approach that use a "file merge" method. The overall code is somewhat simpler than other methods...
#echo off
setlocal EnableDelayedExpansion
set "lineNum=0"
(for /F "tokens=1,2* delims=:x " %%a in ('(type test.txt ^& echo 0x^) ^| findstr /N "[0-9][0-9]*x"') do (
if !lineNum! lss %%a call :locateLine %%a
set "line=%%c"
set /A "count[!line: =_!]+=%%b"
)) < test.txt
set "count[="
(for /F "tokens=2* delims=[]=" %%a in ('set count[') do (
set "item=%%a"
if %%b equ 1 (echo !item:_= !) else echo %%bx !item:_= !
)) > summary.txt
goto :EOF
:locateLine num
set /A "lineNum+=1" & set /P "line=" & if errorlevel 1 exit /B
if %lineNum% lss %1 set /A "count[%line: =_%]+=1" & goto locateLine
exit /B
Another approach (splitting the file into items with and without quantity) (also fixing the Pollux Infusion issue in my first answer):
#echo off
setlocal enabledelayedexpansion
REM process lines without quantity:
for /f "delims=" %%a in ('type test.txt^|findstr /vrc:"[0123456789][0123456789]*x "') do call :count 1 "%%a"
REM process lines with quantity:
for /f "tokens=1*delims=x " %%a in ('type test.txt^|findstr /rc:"[0123456789][0123456789]*x "') do call :count %%a "%%b"
REM reformat:
(for /f "tokens=1,2 delims=#=" %%a in ('set #') do (
set "count=%%bx "
set "line=!count:~0,5!%%a" &REM including '1x'
if %%b==1 set "line= %%a" &REM supressing '1x'
echo !line:_= !
))>summary.txt
type summary.txt
goto :eof
:count
set item=%~2
set "item=%item: =_%"
set /a #%item% +=%1
Included both with and without 1x. Remove the line, you don't want.

How to set name of final output .csv file to the name of the folder?

I have a working Windows batch script which combines multiple CSV files with same headers into one big CSV file. It is as follows:
#echo off
ECHO Set working directory
pushd %~dp0
ECHO Deleting existing combined file
del combined.csv
setlocal ENABLEDELAYEDEXPANSION
set cnt=1
for %%i in (*.csv) do (
if !cnt!==1 (
for /f "delims=" %%j in ('type "%%i"') do echo %%j >> combined.csv
) else if %%i NEQ combined.csv (
for /f "skip=1 delims=" %%j in ('type "%%i"') do echo %%j >> combined.csv
)
set /a cnt+=1
)
I want the output file to be the same name as the folder name, instead of combined.csv.
For example, if the name of the folder is ABC, then output combined CSV file should be ABC.csv.
#echo off
setlocal enableextensions disabledelayedexpansion
pushd "%~dp0"
set "first=1"
for %%a in ("%~dp0\.") do (
del "%%~nxa.csv" 2>nul
(for %%i in (*.csv) do (
if /i not "%%~nxi"=="%%~nxa.csv" if defined first (
set "first="
type "%%~fi"
) else (
(for /f "skip=1 usebackq delims=" %%j in ("%%~fi") do echo(%%j)
)
)) > "%%~fa\%%~nxa.csv"
)

search and replace string using batch commands

How can i search a string and replace it with a variable.
i would like to search version="1.37.0" but the version number could be anything. And there are two "version=" string in package.xml but i would like to replace second one.
how can i search version="x.x.x" and replace it with version="$variable"?
is there any one liner?
i did try to use something like this to search:
findstr "version="[0-9].[0-9].[0-9]" package.xml
and also same thing for desrciption="$variable1"
package.xml
<?xml version="1.0" encoding="utf-8"?>
<PackageManifest>
<Package name="audio"
description="something. . .."
version="1.37.0"
comment="">
</Package>
</PackageManifest>
ad hoc solution, but ...
Edited to adapt to comments
#echo off
setlocal enableextensions disabledelayedexpansion
rem Check input parameters. Needed the input file, the version and the description
if "%~3"=="" goto :eof
set "file=%~1"
set "newVersion=%~2"
set "newDescription=%~3"
rem Read the file into memory
for /f "tokens=1,* delims=:" %%a in ('findstr /n "^" "%file%"') do (
set /a "line=1000+%%a*10"
setlocal enabledelayedexpansion
for %%c in (!line!) do endlocal & set "l_%%c=|%%b"
)
rem %%a will search the required lines
rem %%c remove blanks at the start of the line
rem %%d get the key name
for /f "tokens=2,* delims=_=|" %%a in (
'set l_1 ^| findstr /i /r /c:"^[^<]*version=" /c:"description=" /c:"^[^<]*<Package"'
) do for /f %%c in ("%%b") do for /f "delims==" %%d in ("%%c") do (
if /i "%%d"=="description" ( set "value=%newDescription%" & set "newDescription="
) else if /i "%%d"=="version" ( set "value=%newVersion%" & set "newVersion="
) else if /i "%%d"=="<Package" ( set "packageLine=%%a" & set "value="
) else set "value="
if defined value ( setlocal enabledelayedexpansion
for /f "delims=" %%z in ("!value!") do ( endlocal
for /f tokens^=1^,2^,^*^ delims^=^" %%e in ("%%b") do set "l_%%a=|%%e"%%z"%%g"
)
)
)
rem Include the missing values
set /a "packageLine+=1"
if defined newDescription set "l_%packageLine%=| description="%newDescription%""
set /a "packageLine+=1"
if defined newVersion set "l_%packageLine%=| version="%newVersion%""
rem Output the changed information to console
for /f "tokens=1,* delims=|" %%a in ('set l_1') do echo(%%b
rem Save to file
>"%file%" (for /f "tokens=1,* delims=|" %%a in ('set l_1') do echo(%%b)
Try this :
#echo off
set $FindStr=Version="x.x.x"
set $ReplString=Version="y.y.y"
setlocal enabledelayedexpansion
for /f "delims=" %%a in ('type test.xml') do (
set $Ver=%%a
set $Ver=!$Ver: =!
If /i !$Ver!==%$FindStr% set $Ver=%$ReplString%
echo !$Ver! ) >> Output.xml
Very simplist but a good base
Edit :
This will ask for the version value of the second matched version=
#echo off
set "$FindStr=Version="
set $c=1
setlocal enabledelayedexpansion
for /f "delims=" %%a in ('type test.xml') do (
set $Ver=%%a
set $Ver=!$Ver: =!
If /i "!$Ver:~0,8!"=="%$FindStr%" (
if !$c! GTR 1 (
set /p "$NewVer=Enter New version : "
set $Ver=%$FindStr%!$NewVer!)
set /a $c+=1)
echo !$Ver! >> Output.xml)
The input file is text.xml and the ouputFile Output.xml

How to get a Substring from list of file names

I want to develop the following logic
Read all files in a directory
Extract the first part of the filename – this will be the partner name
Extract anything after the first underscore- this will be filename
Eg: ZZTEST_123_abc_doc.txt  ZZTEST is partner. 123_abc_doc.txt is the filename.
Below is the code I developed
#echo off
setlocal ENABLEDELAYEDEXPANSION
Set Test_Dir=C:\Axway\projects\Cardinal\dosscript\test
cd %Test_Dir%
for /r %%a in (*.*) do (
Set "fname1=%%~nxa"
echo Filename is :!fname1!
for /f "tokens=1 delims=_" %%i in ("!fname1!") do (
Set "partner=%%i"
echo Partner is :!partner!
Set "str_tmp=!partner!_"
echo !str_tmp!
call :strlength length !str_tmp!
echo !length!
set fname=!fname1:~%length%!
echo !fname1:~%length%!
)
)
goto :eof
:strlength
setlocal enableextensions
set "#=%~2"
set length=0
:stringLengthLoop
if defined # (set "#=%#:~1%"&set /A length+=1&goto stringLengthLoop)
endlocal && set "%~1=%length%"
GOTO :EOF
But the result is
ID_ZZRoutingID_filename.txt
Filename is :ZZRoutingID_ZZRoutingID_filename1.txt
Partner is :ZZRoutingID
12
Result: ID_ZZRoutingID_filename1.txt
The result should be ZZRoutingID_filename1.txt but i am getting
ID_ZZRoutingID_filename1.txt.
Please help
The purpose of the length calculation is not clear to me, but I would suggest adding an asterisk following the 1 in your for /f "tokens=1 delims=_". You would then get the "filename" you were looking for through %%j.
I tested it like this:
#echo off
setlocal EnableDelayedExpansion
set source=D:\Program Files\Somewhere
cd %source%
for /r %%i in (*.*) do (
for /f "tokens=1* delims=_" %%j in ( "%%~nxi" ) do (
echo partner: %%j
echo name: %%k
)
)
endlocal
If you do not need to recurse through sub-directories:
#echo off
set source=D:\Program Files\Somewhere
for /f "tokens=1* delims=_" %%i in ( 'dir "%source%" /b /a-d' ) do (
echo partner: %%i
echo filename: %%j
)
dir /b /a-d retrieves the list of a directory's content except its sub-directories:
D:\Program Files\Somewhere>dir /b /a-d
ZZTEST_123_456.txt
ABCDEF_890_FFF.doc
FOOBAR_567_###.zzz

Resources