length of each line using batch file - batch-file

I want to read a CSV file line by line and echo something different if the length of the line is 7999.
I manage to do something as below, which reads each line and checks the number of character for each line, but the issue is that I am getting no value in %result% and echo(%result% prints a blank value. Any idea what am I doing wrong here? Thanks
#echo off
setlocal
for /f "tokens=* delims= " %%a in (REPORTS.csv) do (
set "line=%%a"
call :strlen result line
echo(%result%
if %result% EQU 7999 (
echo %%a
echo(short=%result%
) else (
echo %%a
echo(long=%result%
)
pause
)
:strlen <resultVar> <stringVar>
(
setlocal EnableDelayedExpansion
set "s=!%~2!#"
set "len=0"
for %%P in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
if "!s:~%%P,1!" NEQ "" (
set /a "len+=%%P"
set "s=!s:~%%P!"
)
)
)
(
endlocal
set "%~1=%len%"
exit /b
)

Put this section into another subroutine, similar to :strlen
echo(%result%
if %result% EQU 7999 (
echo %%a
echo(short=%result%
) else (
echo %%a
echo(long=%result%
)
Note also that your main routine will continue into your subroutine when finished, so at end-of-file(reports.csv) the batch will execute :strlen one final time and exit through the EXIT
I'd recommend adding a
GOTO :EOF
Immediately before the :strlen label. This is understood by the processor to go to end-of-physiacl-file (the colon is required)
When a compound statement enclosed in parentheses is to be executed,
the statement is first parsed from the open parenthesis all of the
way to the matching close-parenthesis.
At this time, any %var% is replaced by that var's value from the
environment AT THE TIME IT IS PARSED (ie its PARSE-TIME value.)
THEN if the statement seems valid, it is executed.
There are three common ways of accessing the RUN-TIME value of the
variable (as a FOR loop executes, for instance.)
1/ SETLOCAL ENABLEDELAYEDEXPANSION which switches to a mode where
!var! may be used to access the runtime value of var
2/ CALL set var2=%%var%% to set the value of var2 from the
runtime value of var
3/ Executing a subroutine, internal or external within which %var%
will be the runtime value.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
FOR %%i IN (1 2 3) DO (
ECHO START of run %%i
ECHO using ^!time^! : !time! - PARSE TIME was %time%
CALL ECHO using CALL %%%%TIME%%%% : %%TIME%%
CALL :report
timeout /t 5
ECHO using ^!time^! : !time!
CALL ECHO using CALL %%%%TIME%%%% : %%TIME%%
CALL :report
ECHO END of run %%i
ECHO.
)
GOTO :eof
:report
ECHO :report says TIME is %TIME%
GOTO :eof
A few items to note:
The instruction
IF ERRORLEVEL n echo errorlevel is n OR GREATER
ALWAYS interprets the RUN-TIME value of ERRORLEVEL
IF SET VAR ALWAYS interprets the RUN-TIME value of VAR
The magic variables like ERRORLEVEL and TIME should never
be SET. If you execute
SET ERRORLEVEL=dumb
then ERRORLEVEL will adopt the value dumb because the current
value in the environment takes priority over the system-assigned value.

You should use DelayedExpansion in if and for loops and take care of the brackets:
#echo off
setlocal enabledelayedexpansion
for /f "tokens=* delims= " %%a in (REPORTS.csv) do (
set "line=%%a"
call :strlen result line
echo.!result!
if !result! EQU 7999 (
echo.%%a
echo.short=!result!
) else (
echo.%%a
echo.long=!result!
)
)
pause
goto:eof
:strlen <resultVar> <stringVar>
setlocal EnableDelayedExpansion
set "s=!%~2!#"
set "len=0"
for %%P in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
if "!s:~%%P,1!" NEQ "" (
set /a "len+=%%P"
set "s=!s:~%%P!"
)
)
endlocal &set "%~1=%len%"
exit /b
Your code doesn't ever work in many areas.

Related

Assign each line of the text file to a variable to verify numbers are in sequence in windows batch script

I'm learning windows batch-file script and creating my own scripts to practice the coding but kind of hit a block while try find whether the numbers in a text file is in sequence or not.I have two files,one file(file.txt) contains the number of lines in file_received.txt. The file_received.txt content is below:
1021
1022
1023
1024
1025
1027
1028
I'm building a script to test whether all the numbers in the text file are in sequence .so as a first step I'm trying to extract each line of the file_received to be assigned to a variable through if / for loop but the if command loop assigning all the lines to the variable num from file_received.txt at the same time. Is it possible to assign first line of the file to variable num and increment it as the if loops increment?
setlocal EnableDelayedExpansion
rem assign the number of lines to a variable
set /P var=<C:\files.txt
for /F "tokens=1" %%a in ("%var%") do echo.%%a
rem assign the first variable to var1
set /P var1=<C:\files_received_sequence.txt
for /F "tokens=1" %%a in ("%var1%") do echo.%%a
set /a x=1
:while
if %x% leq %var% (
echo %x%
rem assigning each line to the variable num inside the if loop and will be used in comparison and reser
for /F "tokens=%x%" %%i in (C:\files_received.txt) do set num=%%i
echo %num%
set /a x+=1
goto :while
)
echo test :D
the output is as below in loop 1 the entire file content is assigned to the variable num and from loop 2 to 7 the last number is assigned.
C:\>setlocal EnableDelayedExpansion
C:\>set /P var= 0<C:\files.txt
C:\>for /F "tokens=1" %a in ("7 ") do echo.%a
C:\>echo.7
7
C:\>set /P var1= 0<C:\files_received.txt
C:\>for /F "tokens=1" %a in ("1021") do echo.%a
C:\>echo.1021
1021
C:\>set /a x=1
C:\>if 1 LEQ 7 (
echo 1
for /F "tokens=1" %i in (C:\files_received.txt) do set num=%i
echo
set /a x+=1
goto :while
)
1
C:\>set num=1021
C:\>set num=1022
C:\>set num=1023
C:\>set num=1024
C:\>set num=1025
C:\>set num=1027
C:\>set num=1028
ECHO is on.
C:\>if 2 LEQ 7 (
echo 2
for /F "tokens=2" %i in (C:\files_received.txt) do set num=%i
echo 1028
set /a x+=1
goto :while
)
2
1028
Here's the logic I'd use to test that each number is in sequence incrementing by one (and only one) each time:
#Echo off & Setlocal EnableDelayedExpansion
Set "ln="
For /F "Delims=" %%i in (C:\file_received.txt) Do (
If Not "!ln!"=="" For /F "UseBackQ Delims=" %%v in (`"Set /A Nx=!ln!+1"`) Do (If Not "%%i"=="%%v" (Echo/OoS:!ln!/%%i & Goto :False))2> Nul
Set "ln=%%i"
)
Echo/True
Exit /B 0
:False
Echo/False
Exit /B 1
Here is a version that will highlight the item not in sequence. Do note, that it will test sequence only, in other words ensure the previous result is lower than the next
#echo off & setlocal enabledelayedexpansion
set rev=-1
for /f "delims=" %%a in (files_received.txt) do for %%i in (%%a) do (
if %%i leq !rev! (
echo %%i Out of sequence
) else (
echo %%i
set rev=%%i
)
)
besides you don't use delayed expansion (although you have enabled it), your logic is far too complicated:
#echo off
setlocal enabledelayedexpansion
set last=-1
for /f %%a in (t.txt) do (
if %%a lss !last! (
echo not in sequence
goto :eof
)
set "last=%%a"
)
echo all in sequence.
the variable !last! holds the value from the previous iteration of the loop.
(Depending on your needs, you may want to replace lss with leq)

IF variable LSS variable fails when variable is blank

I have the following batch file that will check and compare two variables, however, it fails when one of the variables are blank.. any ideas how to handle a case where LocalVersion can be blank aka the file version.txt does not exist.
test.bat:
for /f "tokens=1 " %%a in ('%Tools%\cat.exe version.txt') do set LocalVersion=%%a
for /f "tokens=1 " %%a in ('%Tools%\cat.exe \\UNC_Share\version.txt') do set RemoteVersion=%%a
echo LocalVersion %LocalVersion%
echo RemoteVersion %RemoteVersion%
if %LocalVersion% LSS %RemoteVersion% ( goto :skip )
if %LocalVersion% GTR %RemoteVersion% ( goto :Update)
Results:
c:\test.bat
LocalVersion
RemoteVersion 4.0.1
4.0.1 was unexpected at this time.
For comparisons of versions it is strongly recommended not running a literal comparison if the version numbers contain points. It is better to convert the version numbers with points into integers and compare the integers.
Example 1 using multiplications and additions:
#echo off
setlocal EnableExtensions
set "LocalVersion=0.0.0"
set "LocalVersNum=0"
set "RemoteVersion=0.0.0"
set "RemoteVersNum=0"
if exist "version.txt" (
for /F "usebackq tokens=1-3 delims=." %%A in ("version.txt") do (
set "LocalVersion=%%A.%%B.%%C"
set /A LocalVersNum=%%A * 1000000 + %%B * 1000 + %%C
)
)
if exist "\\Sever\Share\version.txt" (
for /F "usebackq tokens=1-3 delims=." %%A in ("\\Sever\Share\version.txt") do (
set "RemoteVersion=%%A.%%B.%%C"
set /A RemoteVersNum=%%A * 1000000 + %%B * 1000 + %%C
)
)
if %LocalVersNum% LSS %RemoteVersNum% goto Skip
if %LocalVersNum% GTR %RemoteVersNum% goto Update
echo %LocalVersion% is equal %RemoteVersion%.
goto EndBatch
:Skip
echo %LocalVersion% is lower %RemoteVersion%.
goto EndBatch
:Update
echo %LocalVersion% is greater %RemoteVersion%.
:EndBatch
endlocal
Example 2 using bit operations:
#echo off
setlocal EnableExtensions
set "LocalVersion=0.0.0"
set "LocalVersNum=0"
set "RemoteVersion=0.0.0"
set "RemoteVersNum=0"
if exist "version.txt" (
for /F "usebackq tokens=1-3 delims=." %%A in ("version.txt") do (
set "LocalVersion=%%A.%%B.%%C"
set /A "LocalVersNum=(%%A << 24) | (%%B << 16) | %%C"
)
)
if exist "\\Sever\Share\version.txt" (
for /F "usebackq tokens=1-3 delims=." %%A in ("\\Sever\Share\version.txt") do (
set "RemoteVersion=%%A.%%B.%%C"
set /A "RemoteVersNum=(%%A << 24) | (%%B << 16) | %%C"
)
)
if %LocalVersNum% LSS %RemoteVersNum% goto Skip
if %LocalVersNum% GTR %RemoteVersNum% goto Update
echo %LocalVersion% is equal %RemoteVersion%.
goto EndBatch
:Skip
echo %LocalVersion% is lower %RemoteVersion%.
goto EndBatch
:Update
echo %LocalVersion% is greater %RemoteVersion%.
:EndBatch
endlocal
Both examples produce the right result for LocalVersion being for example 4.0.10 and RemoteVersion being 4.0.9 on which a literal comparison like if %LocalVersion% LSS %RemoteVersion% goto Skip produces the wrong result.
The command line
if "%LocalVersion%" LSS "%RemoteVersion%" goto Skip
results always in a literal comparison because the double quotes are not ignored on comparing the strings. So with using double quotes the referenced values are not compared anymore after an implicit conversion from string to integer on both values using an integer comparison, but doing a string comparison.
The solution for avoiding an exit of batch execution because of a syntax error if one of the two version.txt files does not exist is an initialization of the used environment variables.
The additional if exist condition before each FOR is for avoiding an error message on execution of command FOR and the appropriate version.txt file does not exist.
FOR reads the version.txt file directly without the tool cat which is ported from Unix to Windows and therefore not available by default on Windows. The native Windows command for cat is type which is most likely not really needed here.

variable as tokens in for loop

Im trying to make a batch file that loops thru an array containing numbers like this: 1 2 3 4 5.
In the first itteration of the loop I like to pick token 1 and 2. In the second 2 and 3, in the third 3 and 4 and so on.
I do think I should use ! in the variables first and second that I use as tokens. Like in the first FOR /F, but when I do, I get: !first!" was not expected here.
And if I use %, it does not count up.
Everything works except the variable tokens. Any one knowes how to? Any help or suggestions greatly appriciated.
This is the part Im struggeling with:
setlocal EnableDelayedExpansion
set first=1
set second=2
set N=4
set output="1 2 3 4 5"
set output=%output:"=%
for /L %%a in (1,1,%N%) do (
if !counter! equ active (
set /a first+=1
set /a second+=1
)
FOR /F "tokens=!first!" %%a IN ("%output%") DO (
set nr1=%%a
)
FOR /F "tokens=%second%" %%a IN ("%output%") DO (
set nr2=%%a
)
echo nr1 var: !nr1!
echo nr2 var: !nr2!
echo counter f: !first!
echo counter s: !second!
set counter=active
)
You cannot use delayed expanded variables in the options string of for /F. Neither can you use other for variables for that. But you can use normally (immediately) expanded variables. Also you can use argument references like %1, for example.
So a nice work-around for your problem is to place the for /F loop in a sub-routine and use call in the main program with the delayed expanded variables as arguments, like this:
#echo off
setlocal EnableDelayedExpansion
set /A first=1
set /A second=2
set /A N=4
set "output=1 2 3 4 5"
set "counter="
for /L %%a in (1,1,%N%) do (
if defined counter (
set /A first+=1
set /A second+=1
)
call :SUB !first! !second!
echo nr1 var: !nr1!
echo nr2 var: !nr2!
echo counter f: !first!
echo counter s: !second!
set "counter=active"
)
endlocal
exit /B
:SUB val_token1 val_token2
for /F "tokens=%~1,%~2" %%a in ("%output%") do (
if %~1 LSS %~2 (
set "nr1=%%a"
set "nr2=%%b"
) else if %~1 GTR %~2 (
set "nr1=%%b"
set "nr2=%%a"
) else (
set "nr1=%%a"
set "nr2=%%a"
)
)
exit /B
Since you are extracting tokens from the same string, I combined your two for /F loops into a single one. The if block in the for /F loop in the sub-routine :SUB is there just in case the second token number is not always greater than the first one. But if that can guaranteed, the for /F loop needs to contain only set "nr1=%%a" and set "nr2=%%b".

Batch - Decreasing value of a variable in substring is not functioning

I'm trying to reverse "hello" to "olleh". But the output shows "ooooo".
I think !string:~%back%,1! is the problem, because when I use echo to test the value of back is decreasing or not, it works, but it doesn't work in substring, so it always get the last character of the string (-1,1).
#echo off
set string=hello
set temp_string=%string%
set /a string_length=0
:find_length
if defined temp_string (
set temp_string=%temp_string:~1%
set /a string_length+=1
goto :find_length
)
:loop
setlocal enabledelayedexpansion
set /a back=-1
for /l %%a in (1,1,!string_length!) do (
set reverse_string=!string:~%back%,1!!reverse_string!
set /a back-=1
)
echo !reverse_string!
pause >nul
As TripeHound commented, %back% needs to be delayed. What you should do is use the for /L loop value of %%a to in place of %back%. (No sense decrementing a variable manually when one's already being decremented for you as a part of the for /L loop, right?)
for /l %%a in (%string_length%,-1,0) do (
call set "reverse_string=!reverse_string!!string:~%%a,1!"
)
goto loops are not very efficient. If you've got a long string you're going to reverse, there'll be a noticeable pause while you count its length if you goto :label for each character. The fastest way I've found to get the length of a string is based on jeb's answer here:
:length <return_var> <string>
setlocal enabledelayedexpansion
if "%~2"=="" (set ret=0) else set ret=1
set "tmpstr=%~2"
for %%I in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
if not "!tmpstr:~%%I,1!"=="" (
set /a ret += %%I
set "tmpstr=!tmpstr:~%%I!"
)
)
endlocal & set "%~1=%ret%"
goto :EOF
Put it all together like this:
#echo off
setlocal
set "string=%*"
call :length string_length "%string%"
setlocal enabledelayedexpansion
for /l %%a in (%string_length%,-1,0) do (
set "reverse_string=!reverse_string!!string:~%%a,1!"
)
echo(!reverse_string!
pause >nul
exit /b 0
:length <return_var> <string>
setlocal enabledelayedexpansion
if "%~2"=="" (set ret=0) else set ret=1
set "tmpstr=%~2"
for %%I in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
if not "!tmpstr:~%%I,1!"=="" (
set /a ret += %%I
set "tmpstr=!tmpstr:~%%I!"
)
)
endlocal & set "%~1=%ret%"
goto :EOF
Example output:
command: test.bat The quick brown fox
result: xof nworb kciuq ehT
The problem is that %back% is being used without delayed expansion, so will always have the value -1. Replacing the end of your code with:
set /a back=-1
set /a count=1
:repeat
if %count% gtr %string_length% goto :report
set reverse_string=!string:~%back%,1!!reverse_string!
set /a back-=1
set /a count+=1
goto :repeat
:report
echo !reverse_string!
Will do the trick.
You cannot just use !back! because you need the contrast of !...! and %...% to have a variable index, so you'll have to go back to an old-fashioned :loop construct so %back% gets updated each time around.
As described at this post:
"To get the value of a substring when the index change inside FOR/IF enclose the substring in double percents and precede the command with call. For example:
for /l %%a in (1,1,!string_length!) do (
call set reverse_string=%%string:~!back!,1%%!reverse_string!
set /a back-=1
)
Another way to achieve previous process is using an additional FOR command to change the delayed expansion of the index by an equivalent replaceable parameter, and then use the delayed expansion for the substring. This method run faster than previous CALL:
for /l %%a in (1,1,!string_length!) do (
for %%b in (!back!) do (
set reverse_string=!string:~%%b,1!!reverse_string!
)
set /a back-=1
)
"
However, it is not efficient to first loop thru the string just to count the characters, and then loop again to reverse they. I think the method below should be the fastest one:
#echo off
setlocal EnableDelayedExpansion
set maxLength=80
set string=hello
set "reverse="
for /L %%i in (1,1,%maxLength%) do (
set "reverse=!string:~0,1!!reverse!"
set "string=!string:~1!"
if not defined string goto break
)
:break
echo %reverse%
Here's another algorithm:
#echo off
call :reverse "The quick brown fox"
echo %output%
pause & exit
:reverse
setlocal enableDelayedExpansion
set string=%~1
set index=0
:loopchar
set char=!string:~%index%,1!
if "!char!"=="" endlocal & set output=%output% & exit /b
set output=!char!!output!
set /a index+=1
goto loopchar
"Tricks":
using %index% inside ! to expand its current value instead of call with %% (#Aacini)
export of !output! from the local scope by reassigning it on the same line as endlocal.

Removing non alphanumeric characters in a batch variable

In batch, how would I remove all non alphanumeric (a-z,A-Z,0-9,_) characters from a variable?
I'm pretty sure I need to use findstr and a regex.
The solutionof MC ND works, but it's really slow (Needs ~1second for the small test sample).
This is caused by the echo "!_buf!"|findstr ... construct, as for each character the pipe creates two instances of cmd.exe and starts findstr.
But this can be solved also with pure batch.
Each character is tested if it is in the map variable
:test
set "_input=Th""i\s&& is not good _maybe_???"
set "_output="
set "map=abcdefghijklmnopqrstuvwxyz 1234567890"
:loop
if not defined _input goto endLoop
for /F "delims=*~ eol=*" %%C in ("!_input:~0,1!") do (
if "!map:%%C=!" NEQ "!map!" set "_output=!_output!%%C"
)
set "_input=!_input:~1!"
goto loop
:endLoop
echo(!_output!
And it could be speed up when the goto loop is removed.
Then you need to calculate the stringLength first and iterate then with a FOR/L loop over each character.
This solution is ~6 times faster than the above method and ~40 times faster than the solution of MC ND
set "_input=Th""i\s&& is not good _maybe_!~*???"
set "_output="
set "map=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890"
%$strLen% len _input
for /L %%n in (0 1 %len%) DO (
for /F "delims=*~ eol=*" %%C in ("!_input:~%%n,1!") do (
if "!map:%%C=!" NEQ "!map!" set "_output=!_output!%%C"
)
)
exit /b
The macro $strlen can be defined with
set LF=^
::Above 2 blank lines are required - do not remove
#set ^"\n=^^^%LF%%LF%^%LF%%LF%^^":::: StrLen pResult pString
set $strLen=for /L %%n in (1 1 2) do if %%n==2 (%\n%
for /F "tokens=1,2 delims=, " %%1 in ("!argv!") do (%\n%
set "str=A!%%~2!"%\n%
set "len=0"%\n%
for /l %%A in (12,-1,0) do (%\n%
set /a "len|=1<<%%A"%\n%
for %%B in (!len!) do if "!str:~%%B,1!"=="" set /a "len&=~1<<%%A"%\n%
)%\n%
for %%v in (!len!) do endlocal^&if "%%~b" neq "" (set "%%~1=%%v") else echo %%v%\n%
) %\n%
) ELSE setlocal enableDelayedExpansion ^& set argv=,
EDITED - #jeb is right. This works but is really, really slow.
#echo off
setlocal enableextensions enabledelayedexpansion
set "_input=Th""i\s&& is not good _maybe_???"
set "_output="
:loop
if not defined _input goto endLoop
set "_buf=!_input:~0,1!"
set "_input=!_input:~1!"
echo "!_buf!"|findstr /i /r /c:"[a-z 0-9_]" > nul && set "_output=!_output!!_buf!"
goto loop
:endLoop
echo !_output!
endlocal
So, back to the drawing board. How to make it faster? lets try to do as less operations as we can and use as much long substring as we can. So, do it in two steps
1.- Remove all bad characters that can generate problems. To do it we will use the hability of for command to identify these chars as delimiters , and then join the rest of the sections of god characters of string
2.- Remove the rest of the bad characters, locating them in string using the valids charactes as delimiters to find substrings of bad characters, replacing then in string
So, we end with (sintax adapted to what has been answered here)
#echo off
setlocal enableextensions enabledelayedexpansion
rem Test empty string
call :doClean "" output
echo "%output%"
rem Test mixed strings
call :doClean "~~asd123#()%%%^"^!^"~~~^"""":^!!!!=asd^>^<bm_1" output
echo %output%
call :doClean "Thi\s&& is ;;;;not ^^good _maybe_!~*???" output
echo %output%
rem Test clean string
call :doClean "This is already clean" output
echo %output%
rem Test all bad string
call :doClean "*******//////\\\\\\\()()()()" output
echo "%output%"
rem Test long string
set "zz=Thi\s&& is not ^^good _maybe_!~*??? "
set "zz=TEST: %zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%"
call :doClean "%zz% TEST" output
echo %output%
rem Time long string
echo %time%
for /l %%# in (1 1 100) do call :doClean "%zz%" output
echo %time%
exit /b
rem ---------------------------------------------------------------------------
:doClean input output
setlocal enableextensions enabledelayedexpansion
set "map=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 "
set "input=%~1"
set "output="
rem Step 1 - Remove critical delimiters
(
:purgeCritical
for /L %%z in (1 1 10) do (
for /f tokens^=1^-9^,^*^ delims^=^=^"^"^~^;^,^&^*^%%^:^!^(^)^<^>^^ %%a in ("!input!") do (
set "output=!output!%%a%%b%%c%%d%%e%%f%%g%%h%%i"
set "input=%%j"
)
if not defined input goto outPurgeCritical
)
goto purgeCritical
)
:outPurgeCritical
rem Step 2 - remove any remaining special character
(
:purgeNormal
for /L %%z in (1 1 10) do (
set "pending="
for /f "tokens=1,* delims=%map%" %%a in ("!output!") do (
set "output=!output:%%a=!"
set "pending=%%b"
)
if not defined pending goto outPurgeNormal
)
goto purgeNormal
)
:outPurgeNormal
endlocal & set "%~2=%output%"
goto :EOF
Maybe not the fastest, but at least a "decent" solution
#echo eof
call :purge "~~asd123#()%%%^"^!^"~~~^:^=asd^>^<bm_1" var
echo (%var%)
goto :eof
:purge StrVar [RtnVar]
setlocal disableDelayedExpansion
set "str1=%~1"
setlocal enableDelayedExpansion
for %%a in ( - ! # # $ % ^^ ^& + \ / ^< ^> . ' [ ] { } ` ^| ^" ) do (
set "str1=!str1:%%a=!"
)
rem dealing with some delimiters
set "str1=!str1:(=!"
set "str1=!str1:)=!"
set "str1=!str1:;=!"
set "str1=!str1:,=!"
set "str1=!str1:^^=!"
set "str1=!str1:^~=!"
set "temp_str="
for %%e in (%str1%) do (
set "temp_str=!temp_str!%%e"
)
endlocal & set "str1=%temp_str%"
setlocal disableDelayedExpansion
set "str1=%str1:!=%"
set "str1=%str1::=%"
set "str1=%str1:^^~=%"
for /f "tokens=* delims=~" %%w in ("%str1%") do set "str1=%%w"
endlocal & set "str1=%str1%"
endlocal & if "%~2" neq "" (set %~2=%str1%) else echo %str1%
goto :eof
Still cannot deal with ~ and = but working on it
EDIT: = now will be cleared
EDIT: ~ now will be cleared

Resources