Page 1 of 2
how can i get position of a character(s) in a string?
Posted: 31 Aug 2007 03:21
by hgulcan
how can i get position of a character(s) in a string?
let the string is "This is the example."
i want to get starting position of "the".
thanks.
Posted: 02 Sep 2007 01:24
by DosItHelp
hgulcan,
Below a findString function and how to use it.
The result of the example is: "Position is: 8"
To try it out copy both code blocks into a new batch file.
Code: Select all
@ECHO OFF
set "s=This is the example."
call:findString s "the" pos
if not defined pos echo.Substring not found&goto:eof
echo.Position is: %pos%
goto:eof
Code: Select all
:findString -- returns the zero based postion of one string in another string of maximum length of 1023 characters
:: -- %~1: in - varible name of a string to be serached
:: -- %~1: in - string to be found
:: -- %~3: out- return variable name, will be set to position or undefined if string not found
SETLOCAL ENABLEDELAYEDEXPANSION
set "str=!%~1!"
set "str=!str:%~2=@@@@!
set "str=%str:@@@@="&REM %
if "%str%"=="!%~1!" (
ENDLOCAL&IF "%~3" NEQ "" SET "%~3="
GOTO:EOF
)
set str=A!str!& rem keep the A up front to ensures we get the length and not the upper bond
rem it also avoids trouble in case of empty string
set len=0
set /a n=1024
set /a n^>^>=1, len+=n
if !str:~%len%!. == . set /a len-=n
set /a n^>^>=1, len+=n
if !str:~%len%!. == . set /a len-=n
set /a n^>^>=1, len+=n
if !str:~%len%!. == . set /a len-=n
set /a n^>^>=1, len+=n
if !str:~%len%!. == . set /a len-=n
set /a n^>^>=1, len+=n
if !str:~%len%!. == . set /a len-=n
set /a n^>^>=1, len+=n
if !str:~%len%!. == . set /a len-=n
set /a n^>^>=1, len+=n
if !str:~%len%!. == . set /a len-=n
set /a n^>^>=1, len+=n
if !str:~%len%!. == . set /a len-=n
set /a n^>^>=1, len+=n
if !str:~%len%!. == . set /a len-=n
set /a n^>^>=1, len+=n
if !str:~%len%!. == . set /a len-=n
( ENDLOCAL & REM RETURN VALUES
IF "%~3" NEQ "" SET %~3=%len%
)
GOTO:EOF
DosItHelp?
Posted: 02 Sep 2007 14:46
by jeb
Hi,
nice trick to truncate the string.
But here is a little bit better version, that work also for (should work for all strings)
set "s=This@@@@ is the example."
call:findString s "the" pos
:findString -- returns the zero based postion of one string in another string of maximum length of 1023 characters
:: -- %~1: in - varible name of a string to be serached
:: -- %~2: in - string to be found
:: -- %~3: out- return variable name, will be set to position or undefined if string not found
SETLOCAL ENABLEDELAYEDEXPANSION
set "str=!%~1!"
REM set "str=!str:%~2=@@@@!
REM set "str=%str:@@@@="&REM %
set "str=!str:%~2="!
...
btw. Has the <&rem %> part in <set "str=%str:@@@@="&REM %>
a special meaning or is the line
<set "str=%str:@@@@="%> always equivalent?
Posted: 07 Sep 2007 21:43
by DosItHelp
jeb,
- set "str=!%~1!"
str is now "This is the example"
- set "str=!str:%~2=@@@@!
str is now "This is @@@@ example"
- set "str=%str:@@@@="&REM %
this finally truncates the string, i.e. before executing it evaluates to:
set "str="This is "&REM example
so that str is now "This is ".
How does your example get rid of the stuff after "the"?
Posted: 07 Sep 2007 22:37
by DosItHelp
Speaking of "better"...
Code: Select all
:findString -- returns position of first occurrence of a string in another string, case sensitive, maximum string length is 1023 characters
:: -- %~1: in - varible name of a string to be searched
:: -- %~1: in - string to be found
:: -- %~3: out- return variable name, will be set to position or undefined if string not found
:$source http://www.dostips.com
SETLOCAL ENABLEDELAYEDEXPANSION
set "pos="
set "str=!%~1!"
for /L %%a in (0,1,1023) do (
set "s=!str:~%%a!"
if not defined pos if "%~2!s:*%~2=!"=="!s!" set "pos=%%a"
)
ENDLOCAL & IF "%~3" NEQ "" SET "%~3=%pos%"
GOTO:EOF
Code: Select all
:findStringNoCase -- returns position of first occurrence of a string in another string, NOT case sensitive, maximum string length is 1023 characters
:: -- %~1: in - varible name of a string to be searched
:: -- %~1: in - string to be found
:: -- %~3: out- return variable name, will be set to position or undefined if string not found
:$source http://www.dostips.com
SETLOCAL ENABLEDELAYEDEXPANSION
set "pos="
set "str=!%~1!"
for /L %%a in (0,1,1023) do (
set "s=!str:~%%a!"
if not defined pos if /i "%~2!s:*%~2=!"=="!s!" set "pos=%%a"
)
ENDLOCAL & IF "%~3" NEQ "" SET "%~3=%pos%"
GOTO:EOF
Code: Select all
:findStringFromEnd -- returns position of last occurrence of a string in another string, case sensitive, maximum string length is 1023 characters
:: -- %~1: in - varible name of a string to be searched
:: -- %~1: in - string to be found
:: -- %~3: out- return variable name, will be set to position or undefined if string not found
:$source http://www.dostips.com
SETLOCAL ENABLEDELAYEDEXPANSION
set "pos="
set "str=!%~1!"
for /L %%a in (0,1,1023) do (
set "s=!str:~%%a!"
if /i "%~2!s:*%~2=!"=="!s!" set "pos=%%a"
)
ENDLOCAL & IF "%~3" NEQ "" SET "%~3=%pos%"
GOTO:EOF
Code: Select all
:findStringFromEndNoCase -- returns position of last occurrence of a string in another string, NOT case sensitive, maximum string length is 1023 characters
:: -- %~1: in - varible name of a string to be searched
:: -- %~1: in - string to be found
:: -- %~3: out- return variable name, will be set to position or undefined if string not found
:$source http://www.dostips.com
SETLOCAL ENABLEDELAYEDEXPANSION
set "pos="
set "str=!%~1!"
for /L %%a in (0,1,1023) do (
set "s=!str:~%%a!"
if "%~2!s:*%~2=!"=="!s!" set "pos=%%a"
)
ENDLOCAL & IF "%~3" NEQ "" SET "%~3=%pos%"
GOTO:EOF
Posted: 10 Sep 2007 02:34
by jeb
Hi all,
your Version
Code: Select all
set "str=!%~1!" -- str is now "This is the example"
set "str=!str:%~2=@@@@! -- str is now "This is @@@@ example"
set "str=%str:@@@@="&REM % -- this finally truncates the string, i.e. before executing it evaluates to:
-- set "str="This is "&REM example
> so that str is now "This is ".
> How does your example get rid of the stuff after "the"?
My Variant simple expand to
Code: Select all
set "str=!str:%~2="! -- expand to set "str=This is"example
All text after the second " will be ignored without any error.
I suppose your first solution with using of strlen is faster than the others
with "extreme searching", but dont tested it yet.
Posted: 12 Sep 2007 23:20
by DosItHelp
jeb,
Yes you are right the binary approach is much faster.
The problem with using <set "str=!str:%~2="!> is that the search string may occur multiple times, e.g. if %~2 expands to the letter h then:
Code: Select all
set "str=!str:%~2="! -- expands to set "str=T"is is t"e example
which causes an error saying:
is was unexpected at this time.When changing the example string from "This" to "That" to "That is the example" then:
Code: Select all
set "str=!str:%~2="! -- expands to set "str=T"at is t"e example
which causes same error:
is was unexpected at this time.
I expected it would complain about
at now, but no.
Very confusing isn't it?
Re: how can i get position of a character(s) in a string?
Posted: 31 May 2011 10:18
by Ed Dyreen
What is the trick @DosItHelp is using in this line:
set "str=%str:@@@@="&REM %
>>&REM %<< ?
and why do they prefer this
set "str=!str:%~2="!
over this ?
set "str=!str:%~2=!"
yes, I know a little about the parser, but in practice it's a lot of guessing for me.
Re: how can i get position of a character(s) in a string?
Posted: 31 May 2011 11:33
by orange_batch
Yeah, I honestly wonder about voodoo syntax like that myself. How the heck does it make any sense? lol
Re: how can i get position of a character(s) in a string?
Posted: 31 May 2011 12:27
by dbenham
orange_batch wrote:Yeah, I honestly wonder about voodoo syntax like that myself. How the heck does it make any sense? lol
DosItHelp is injecting a command into the string replacement processing.
----------
Have I solved all the issues? and is it worth all the code?
Code: Select all
@echo off
setlocal disableDelayedExpansion
set "str=This! &"@@@@^&"&" is the string with the multiple problems"
set "search=the"
setlocal enableDelayedExpansion
echo str=!str!
set "str=!str:"=""!"
set "cmd=set ^"str2=!str:%search%="&rem!"
echo cmd=!cmd!
setlocal disableDelayedExpansion
%cmd%
setlocal enableDelayedExpansion
set "result=!str2:""="!"
echo result=[!result!]
output:
Code: Select all
str=This! &"@@@@&"&" is the string with the multiple problems
cmd=set "str2=This! &""@@@@&""&"" is "&rem string with "&rem multiple problems
result=[This! &"@@@@&"&" is ]
Dave Benham
Addendum - Oops - should probably double up quotes in search string as well with one more search and replace.
Re: how can i get position of a character(s) in a string?
Posted: 31 May 2011 16:40
by Ed Dyreen
It will still take me time to figure out the exact workings, cause I need to be sure I understand it fully &so when to use it.
I am turning this forum upside down, cause it holds secrets no other sites mention.
Too bad I didn't discover Dostips in 2006. I've googled often enough for the words DOS, CMD &commandline help
Dave, thank u very much for your dedication in explaining things
Re: how can i get position of a character(s) in a string?
Posted: 31 May 2011 16:50
by Cleptography
Ed Dyreen wrote:I am turning this forum upside down, cause it holds secrets no other sites mention.
@Ed
What secrets do you speak of, like prizes at the bottom of a box of Captin Crunch?
Re: how can i get position of a character(s) in a string?
Posted: 31 May 2011 16:52
by Ed Dyreen
YES, I can't leave until I know
EVERYTHING, I'm autistic
but they say it passes into other obsessions every 10 years or so.
Re: how can i get position of a character(s) in a string?
Posted: 31 May 2011 16:57
by Cleptography
Re: how can i get position of a character(s) in a string?
Posted: 01 Jun 2011 15:44
by jeb
dbenham wrote:Have I solved all the issues? and is it worth all the code?
No
It fails even with doubling the quotes, the problem is now
^"It seems to be a general problem if you leave the quotes in the text, you got also problems with the carets.
Code: Select all
set "str=This! &"@@@@^&"&" is^^"& the string with the multiple problems"
And using the %cmd%, you always got problems with <LF> and <CR>, the <CR> are removed, and <LF> breaks the parsing immediatly.
My last solution (delayed expansion with a quote) fails with multiple occurence of the search string.
Therefore I try a new way of splitting the rest with a FOR /F and <LF> combination.
Code: Select all
@echo off
setlocal
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"
set LF=^
rem TWO Empty lines are neccessary
set "str=This! &"@@@@^&"&" is^^"& the string with the multiple problems"
call :strip str "the"
setlocal EnableDelayedExpansion
goto :eof
:strip
setlocal EnableDelayedExpansion
set "var=!%~1!"
echo input=!var!
REM *** Here is the trick, we replace the SEARCH-Text with a <LF>
REM *** Later the <LF> breaks the FOR /F loop
for %%a in ("!LF!") do set "var=!var:%~2=%%~a!"
for /F "tokens=* delims=" %%1 in ("!var!") DO (
set "result=%%1"
goto :leaveLoop
)
:leaveLoop
echo result=!result!
goto :eof
To preserve the carets and exclamation marks you could use it with the
"secure return" technic.
jeb