npocmaka
Latest versions:
SPLIT
Code: Select all
:split [%1 - string to be splitted;%2 - split by;%3 - possition to get; %4 - if defined will store the result in variable with same name]
setlocal EnableDelayedExpansion
set "string=%~2%~1"
set "splitter=%~2"
set /a position=%~3
set LF=^
rem ** Two empty lines are required
echo off
for %%L in ("!LF!") DO (
for /f "delims=" %%R in ("!splitter!") do (
set "var=!string:%%~R%%~R=%%~L!"
set "var=!var:%%~R=%%~L!"
if "!var!" EQU "!string!" (
echo "%~1" does not contain "!splitter!" >&2
exit /B 1
)
)
)
if "!var!" equ "" (
endlocal & if "%~4" NEQ "" ( set "%~4=")
)
if !position! LEQ 0 ( set "_skip=" ) else (set "_skip=skip=%position%")
for /f "eol= %_skip% delims=" %%P in (""!var!"") DO (
if "%%~P" neq "" (
set "part=%%~P"
goto :end_for
)
)
set "part="
:end_for
if not defined part (
endlocal
echo Index Out Of Bound >&2
exit /B 2
)
endlocal & if "%~4" NEQ "" (set %~4=%part%) else echo %part%
exit /b 0
Code: Select all
:indexof [%1 - string ; %2 - find index of ; %3 - if defined will store the result in variable with same name]
@echo off
setlocal enableDelayedExpansion
set "str=%~1"
set "s=!str:%~2=&rem.!"
set s=#%s%
if "%s%" equ "#%~1" endlocal& if "%~3" neq "" (set %~3=-1&exit /b 0) else (echo -1&exit /b 0)
set "len=0"
for %%A in (2187 729 243 81 27 9 3 1) do (
set /A mod=2*%%A
for %%Z in (!mod!) do (
if "!s:~%%Z,1!" neq "" (
set /a "len+=%%Z"
set "s=!s:~%%Z!"
) else (
if "!s:~%%A,1!" neq "" (
set /a "len+=%%A"
set "s=!s:~%%A!"
)
)
)
)
endlocal & if "%~3" neq "" (set %~3=%len%) else echo %len%
exit /b 0
Code: Select all
:lastindexof [%1 - string ; %2 - find last index of ; %3 - if defined will store the result in variable with same name]
@echo off
setlocal enableDelayedExpansion
set "str=%~1"
set "splitter=%~2"
set LF=^
rem ** Two empty lines are required
echo off
for %%L in ("!LF!") DO (
for /f "delims=" %%R in ("!splitter!") do (
set "var=!str:%%R=%%L!"
)
)
for /f delims^=^" %%P in ("!var!") DO (
set "last_part=%%~P"
)
if "!last_part!" equ "" if "%~3" NEQ "" (
echo "not contained" >2
endlocal
set %~3=-1
exit
) else (
echo "not contained" >2
endlocal
echo -1
)
setlocal DisableDelayedExpansion
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"
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=,
%$strlen% strlen,str
%$strlen% plen,last_part
%$strlen% slen,splitter
set /a lio=strlen-plen-slen
endlocal & if "%~3" NEQ "" (set %~3=%lio%) else echo %lio%
exit /b 0
Code: Select all
:reverse [%1 - string to reverse ; %2 - if defined will store the result in variable with same name]
@echo off
setlocal disableDelayedExpansion
set "str=%~1"
set LF=^
rem ** Two empty lines are required
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"
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=,
%$strLen% len,str
setlocal enableDelayedExpansion
set /a half=len/2
set "res=!str:~%half%,-%half%!"
for /L %%C in (%half%,-1,0) do (
set /a len=%len%-1-%%C
if %%C neq %half% (
for %%c in (!len!) do (
set "res=!str:~%%c,1!!res!!str:~%%C,1!"
)
)
)
endlocal & endlocal & if "%~2" NEQ "" (set %~2=%res%) else echo %res%
Code: Select all
:startsWith [%1 - string to be checked;%2 - string for checking ]
@echo off
rem :: sets errorlevel to 1 if %1 starts with %2 else sets errorlevel to 0
setlocal EnableDelayedExpansion
set "string=%~1"
set "checker=%~2"
rem set "var=!string:%~2=&echo.!"
set LF=^
rem ** Two empty lines are required
rem echo off
for %%L in ("!LF!") DO (
for /f "delims=" %%R in ("!checker!") do (
rem set "var=!string:%%~R%%~R=%%~L!"
set "var=!string:%%~R=#%%L!"
)
)
for /f "delims=" %%P in (""!var!"") DO (
if "%%~P" EQU "#" goto :yes
goto :no
)
:yes
endlocal & verify set_error 2>nul
goto :eof
:no
endlocal & ( echo | shift )
goto :eof
Code: Select all
:endsWith [%1 - string to be checked;%2 - string for checking ]
@echo off
rem :: sets errorlevel to 1 if %1 ends with %2 else sets errorlevel to 0
setlocal EnableDelayedExpansion
set "string=%~1"
set "checker=%~2"
rem set "var=!string:%~2=&echo.!"
set LF=^
rem ** Two empty lines are required
rem echo off
for %%L in ("!LF!") DO (
for /f "delims=" %%R in ("!checker!") do (
rem set "var=!string:%%~R%%~R=%%~L!"
set "var=!string:%%~R=%%L#!"
)
)
for /f "delims=" %%P in (""!var!"") DO (
set "temp=%%~P"
)
if "%temp%" EQU "#" goto :yes
goto :no
:yes
endlocal & verify set_error 2>nul
goto :eof
:no
endlocal & ( echo | shift )
goto :eof
Code: Select all
@echo off
:split
setlocal
set string=%~1
set splitter=%~2
set /a position=%~3
setlocal enabledelayedexpansion
rem /--------------
rem Here I'm searching for
rem a suitable specaial character
rem to replace the strinq for splitting
rem with and to use it for processing
rem with FOR /F command
rem ---------------/
for %%C in (¬ ¦ ¶ § ± ° • » « µ г м ж ¦ з - - Х ¬ л ¦ у ) do (
set temp_string=!string:%%C=!
rem if the current special symbol is not part of the splitted string we can use it
if "!temp_string!" EQU "!string!" (
for /f "delims=" %%R in ("!splitter!") do (
set temp_string=!string:%%R=%%C!
)
set "char=%%C"
goto :parametrize_for
)
)
echo You are passing binary string , arent you? Cannot help you.
endlocal
exit /B 1
:parametrize_for
endlocal & set char=%char% & set temp_string=%temp_string%
rem creating the for /f with needed parameters
set "p_for=for /f "tokens=%position% delims=%char%" %%S in ("%temp_string%")"
%p_for% do (
echo %%S
)
goto :eof
I still have no enough courage to try with a string that contains quotes...
The idea is to substitute the string we need to split by , with a single special symbol (which is not part of the string) and then to use FOR /F
(I'm not sure how this line will be displayed (¬ ¦ ¶ § ± ° • » « µ г м ж ¦ з - - Х ¬ л ¦ у ) - it depends on localization , but it should be possible to be copied)
Another thing is the parametrization of the last FOR - I'm using a variable passed directly as a command .Unfortunately this does not work with delayed expansion.
Also I've tried to avoid using of CALL - may be the performance is better that way...
Last edited by npocmaka (13 Sep 2013 11:45)
----------------------------
#15 Apr 2013 09:35
jeb
There exists another way to split at strings.
Replacing the string-splitter with a LF.
Code: Select all
@echo off
@echo off
setlocal DisableDelayedExpansion
set "string=%~1"
set "splitter=%~2"
setlocal EnableDelayedExpansion
set LF=^
rem ** Two empty lines are required
echo off
for %%L in ("!LF!") DO (
for /f "delims=" %%R in ("!splitter!") do (
set "var=!string:%%R=%%L!"
)
)
for /f "delims=" %%P in (""!var!"") DO echo '%%~P'
Code: Select all
test #Split$Hello#Split$Hallo#Split$ #Split$
Code: Select all
''
'Hello'
'Hallo'
''
----------------------------
#15 Apr 2013 23:48
npocmaka
Ha! That was clever

As I still want to grab only specified part of the string I've added some things to your code:
Code: Select all
@echo off
setlocal DisableDelayedExpansion
set "string=%~1"
set "splitter=%~2"
set /a position=%~3
setlocal EnableDelayedExpansion
set LF=^
rem ** Two empty lines are required
echo off
for %%L in ("!LF!") DO (
for /f "delims=" %%R in ("!splitter!") do (
set "var=!string:%%R=%%L!"
echo !var!
rem if "!var!" EQU "!string!" (
rem echo "!string!" does not contain "!splitter!"
rem exit /B 1
rem )
)
)
set /a counter=0
for /f delims^=^" %%P in ("!var!") DO (
set /a counter=!counter!+1
if !counter! EQU !position! (
echo %%~P
endlocal
exit /B 0
)
)
echo Index Out Of Bound
endlocal
exit /B 2
Last edited by npocmaka (15 Apr 2013 23:54)
----------------------------
#24 Jun 2013 13:59
jeb
LF can be part of a command line parameter.npocmaka wrote:
Ha! That was clever- as there's no way to pass LF as a part of command line parameter, and harder in a script.
Code: Select all
c:\temp> myBatch.bat Hello^
world
----------------------------
#24 Jun 2013 19:38
Aacini
This is another example of the usefulness of !1, !2 ... (if such a thing would be possible), besides to take parameters inside a block after SHIFT: ( shift & echo !1 )jeb wrote:
LF can be part of a command line parameter.
c:\temp> myBatch.bat Hello^
world
But it's (nearly) impossible to get the parameter in a secure way.
Is there a way to propose this modification to Microsoft? smile
----------------------------
#08 Sep 2013 12:51
npocmaka
Just saw this post by jeb:
And this is the first time I ever see this: set "part=%%str:%~3=&rem.%%"
Which helps to create a much shorter version of the splitting script:
Code: Select all
:splitter [%1 - string to be splitted;%2 - split by;%3 - possition to get]
@echo off
setlocal enableDelayedExpansion
set "string=%~1"
set /a position=%~3-1
::prepeare for
set "_for=for /f "skip=%position% delims=" %%S in"
set "p=!string:%~2=&echo.!"
%_for% ('echo !p!') do (
echo %%S
goto :endfor
)
:endfor
endlocal
And this is just another way to set a new line as a variable (quotes are critical on the second line.And works only with set .For instance echo "%nl:_=&echo(%" won't work ):
Code: Select all
C:\>set nl=_
C:\>set "nl=%nl:_=&echo(%"
C:\>echo ~%nl%~
~
~
And a way to set a command result to variable without for /f
Code: Select all
set command_result=_
set "command_result=%command_result:_=&dir%"
echo %comand_result%
Probably this is well known but was new for me

Last edited by npocmaka (08 Sep 2013 12:55)
----------------------------
#08 Sep 2013 15:35
foxidrive
You had left an m out of the last line - but this sets a variable to &dir and executes the command.npocmaka wrote:
And a way to set a command result to variable without for /f
Code: Select all
set command_result=_ set "command_result=%command_result:_=&dir%" echo %command_result%
It doesn't set the result of the command into a variable.
----------------------------
#08 Sep 2013 15:41
dbenham
I was just going to point out the same.
The NL variable suffers the same problem.
----------------------------
#08 Sep 2013 19:40
npocmaka
Aaahh. That makes more sense.Nevertheless it's a great trick.
----------------------------
#08 Sep 2013 22:07
npocmaka
I liked the jeb's indexof so I decided to improve it a little bit (there's a built-in strlen to avoid CALLs).Plus I one last index of subroutine (with strlen macro stolen from dostips again from jeb - for this I need three calculations of string length so the macro is need for better performance) and small improvements in split.
Code: Select all
@echo off
:split [%1 - string to be splitted;%2 - split by;%3 - possition to get; %4 - if defined will store the result in variable with same name]
setlocal EnableDelayedExpansion
set "string=%~1"
set "splitter=%~2"
set /a position=%~3
set LF=^
rem ** Two empty lines are required
echo off
for %%L in ("!LF!") DO (
for /f "delims=" %%R in ("!splitter!") do (
set "var=!string:%%R=%%L!"
if "!var!" EQU "!string!" (
echo "!string!" does not contain "!splitter!" >2
exit /B 1
)
)
)
if !position! equ 0 ( set "_skip=" ) else (set "_skip=skip^=%position%^")
for /f %_skip% delims^=^" %%P in ("!var!") DO (
set "part=%%~P"
goto :end_for
)
:end_for
if "!part!" equ "" echo Index Out Of Bound >2 &exit /B 2
endlocal & if "%~4" NEQ "" (set %~4=%part%) else echo %part%
exit /b 0
Code: Select all
:indexof [%1 - string ; %2 - find index of ; %3 - if defined will store the result in variable with same name]
@echo off
setlocal enableDelayedExpansion
set "str=%~1"
set "s=!str:%~2=&rem.!"
set s=#%s%
if "%s%" equ "#%~1" endlocal& if "%~3" neq "" (set %~3=-1&exit /b 0) else (echo -1&exit /b 0)
set "len=0"
for %%A in (2187 729 243 81 27 9 3 1) do (
set /A mod=2*%%A
for %%Z in (!mod!) do (
if "!s:~%%Z,1!" neq "" (
set /a "len+=%%Z"
set "s=!s:~%%Z!"
) else (
if "!s:~%%A,1!" neq "" (
set /a "len+=%%A"
set "s=!s:~%%A!"
)
)
)
)
endlocal & if "%~3" neq "" (set %~3=%len%) else echo %len%
exit /b 0
Code: Select all
:lastindexof [%1 - string ; %2 - find last index of ; %3 - if defined will store the result in variable with same name]
@echo off
setlocal enableDelayedExpansion
set "str=%~1"
set "p=!str:%~2=&echo.!"
set "splitter=%~2"
set LF=^
rem ** Two empty lines are required
echo off
for %%L in ("!LF!") DO (
for /f "delims=" %%R in ("!splitter!") do (
set "var=!str:%%R=%%L!"
)
)
for /f delims^=^" %%P in ("!var!") DO (
set "last_part=%%~P"
)
if "!last_part!" equ "" if "%~3" NEQ "" (
echo "not contained" >2
endlocal
set %~3=-1
exit
) else (
echo "not contained" >2
endlocal
echo -1
)
setlocal DisableDelayedExpansion
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"
set argv=original
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=,
%$strlen% strlen,str
%$strlen% plen,last_part
%$strlen% slen,splitter
set /a lio=strlen-plen-slen
endlocal & if "%~3" NEQ "" (set %~3=%lio%) else echo %lio%
exit /b 0
#11 Sep 2013 21:14
npocmaka
The split was not pretty accurate in the last version- if I have two new lines after the substitution I'll be not able to skip to the right line in the last FOR loop.And I'm not sure if the string starts with the splitting string or not.So here's the fix:
Code: Select all
:split [%1 - string to be splitted;%2 - split by;%3 - possition to get; %4 - if defined will store the result in variable with same name]
setlocal EnableDelayedExpansion
set "string=%~2%~1"
set "splitter=%~2"
set /a position=%~3
set LF=^
rem ** Two empty lines are required
echo off
for %%L in ("!LF!") DO (
for /f "delims=" %%R in ("!splitter!") do (
set "var=!string:%%~R%%~R=%%~L!"
set "var=!var:%%~R=%%~L!"
if "!var!" EQU "!string!" (
echo "%~1" does not contain "!splitter!" >&2
exit /B 1
)
)
)
if "!var!" equ "" (
endlocal & if "%~4" NEQ "" ( set "%~4=")
)
if !position! LEQ 0 ( set "_skip=" ) else (set "_skip=skip=%position%")
for /f "eol= %_skip% delims=" %%P in (""!var!"") DO (
if "%%~P" neq "" (
set "part=%%~P"
goto :end_for
)
)
set "part="
:end_for
if not defined part (
endlocal
echo Index Out Of Bound >&2
exit /B 2
)
endlocal & if "%~4" NEQ "" (set %~4=%part%) else echo %part%
exit /b 0
(And will keep the latest versions of these string functions on the first post)
Last edited by npocmaka (12 Sep 2013 09:15)
----------------------------
#12 Sep 2013 10:04
npocmaka
and one :reverse subroutine (again cannot deal with special characters):
Code: Select all
:reverse [%1 - string to reverse ; %2 - if defined will store the result in variable with same name]
@echo off
setlocal disableDelayedExpansion
set "str=%~1"
set LF=^
rem ** Two empty lines are required
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"
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=,
%$strLen% len,str
setlocal enableDelayedExpansion
set /a half=len/2
set "res=!str:~%half%,-%half%!"
for /L %%C in (%half%,-1,0) do (
set /a len=%len%-1-%%C
if %%C neq %half% (
for %%c in (!len!) do (
set "res=!str:~%%c,1!!res!!str:~%%C,1!"
)
)
)
endlocal & endlocal & if "%~2" NEQ "" (set %~2=%res%) else echo %res%
#13 Sep 2013 11:47
npocmaka
and startsWith and endsWith functions:
startsWith:
Code: Select all
:startsWith [%1 - string to be checked;%2 - string for checking ]
@echo off
rem :: sets errorlevel to 1 if %1 starts with %2 else sets errorlevel to 0
setlocal EnableDelayedExpansion
set "string=%~1"
set "checker=%~2"
rem set "var=!string:%~2=&echo.!"
set LF=^
rem ** Two empty lines are required
rem echo off
for %%L in ("!LF!") DO (
for /f "delims=" %%R in ("!checker!") do (
rem set "var=!string:%%~R%%~R=%%~L!"
set "var=!string:%%~R=#%%L!"
)
)
for /f "delims=" %%P in (""!var!"") DO (
if "%%~P" EQU "#" goto :yes
goto :no
)
:yes
endlocal & verify set_error 2>nul
goto :eof
:no
endlocal & ( echo | shift )
goto :eof
Code: Select all
:endsWith [%1 - string to be checked;%2 - string for checking ]
@echo off
rem :: sets errorlevel to 1 if %1 ends with %2 else sets errorlevel to 0
setlocal EnableDelayedExpansion
set "string=%~1"
set "checker=%~2"
rem set "var=!string:%~2=&echo.!"
set LF=^
rem ** Two empty lines are required
rem echo off
for %%L in ("!LF!") DO (
for /f "delims=" %%R in ("!checker!") do (
rem set "var=!string:%%~R%%~R=%%~L!"
set "var=!string:%%~R=%%L#!"
)
)
for /f "delims=" %%P in (""!var!"") DO (
set "temp=%%~P"
)
if "%temp%" EQU "#" goto :yes
goto :no
:yes
endlocal & verify set_error 2>nul
goto :eof
:no
endlocal & ( echo | shift )
goto :eof