Batch file error "/100 was unexpected at this time" - windows

I make a game for fun with batch script but in this code i have an error message "/100 unexpected at this time" i really don't understand why? Please help me!!
#echo off
mode con cols=110 lines=32
setlocal enabledelayedexpansion
set npctier=0
goto randomnpc
:randomnpc
if %npctier% EQU 0 (
set npctype=Wooden Dummy
set /a npclvl=%random% %% 5+1
set /a npchp=%npclvl% * 100
set /a npcdmg=0
set /a npcdef=(%npchp%*5)/100
set /a npcxp=%npclvl%*100 )
:combatchoice
echo.
echo. You see %npctype% level %npclvl%.
echo.
echo. The %npctype%'s Health: %npchp% HP
echo.
goto main

I recommend to first open a command prompt, run set /? and read the output help carefully and completely from top of first to bottom of last page. There is explained:
Any non-numeric strings in the expression are treated as environment variable names whose values are converted to numbers before using them. If an environment variable name is specified but is not defined in the current environment, then a value of zero is used. This allows you to do arithmetic with environment variable values without having to type all those % signs to get their values.
So there can be written just set /A npchp=npclvl * 100 as npclvl inside the arithmetic expression is interpreted as name of an environment variable and the command line works even on being inside a command block starting with ( and ending with matching ) without usage of delayed environment variable expansion.
Then run cmd /? and read again the output help carefully and completely from top of first to bottom of last page. There is explained that a file name (or any other argument string) containing a space one of these characters &()[]{}^=;!'+,`~ must be enclosed in " to get those characters interpreted as literal characters of an argument string.
Please read also How does the Windows Command Interpreter (CMD.EXE) parse scripts?
For that reason the command line set /a npcdef=(%npchp%*5)/100 should be written with one of the following notations:
set /A npcdef=npchp*5/100
set /A npcdef=npchp * 5 / 100
set /A "npcdef=(npchp*5)/100"
set /A npcdef=(npchp*5^)/100
The caret character ^ escapes the next character for being interpreted as literal character except the next character is % which must be escaped with %.
The recommendations posted on DosTips forum topic ECHO. FAILS to give text or blank line - Instead use ECHO/ should be also taken into account on writing batch files which output empty lines.
The batch file with the main improvement of changing the IF condition to avoid completely the usage of a command block.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
%SystemRoot%\System32\mode.com con cols=110 lines=32
set npctier=0
set "npctype=Wooden Dummy"
:randomnpc
if %npctier% NEQ 0 goto CombatChoice
set /A npclvl=%random% %% 5 + 1
set /A npchp=npclvl*100
set npcdmg=0
set /A npcdef=npchp*5/100
set /A npcxp=npclvl*100
:CombatChoice
echo/
echo You see %npctype% level %npclvl%.
echo/
echo The %npctype%'s health: %npchp% HP
echo/
endlocal
See also Why is no string output with 'echo %var%' after using 'set var = text' on command line? It contains several hints on how to use command SET not written in help/documentation of this command.

If you wish to maintain the same structure, then something lke this would be better:
#Echo Off
SetLocal EnableExtensions
%__APPDIR__%mode.com 110, 32
Set "npctier=0"
:randomnpc
If %npctier% Equ 0 (
Set "npctype=Wooden Dummy"
Set "npcdmg=0"
Set /A "npclvl=(%RANDOM% %% 5) + 1"
Set /A "npchp=npclvl * 100, npcdef=npclvl * 5, npcxp=npchp"
)
:combatchoice
Echo=
Echo You see %npctype% level %npclvl%.
Echo=
Echo The %npctype%'s Health: %npchp% HP
Echo=
GoTo main
You should note, that it is possible to define multiple values using Set /A in one arithmetic instruction

Before you get too carried away with creating a lengthy script which repeats code, I think it's worthwhile introducing you to batch macro's.
Macro's in Batch are commands or command blocks assigned to variables, and through the use of For loops combined with If / Else conditioning can be used to Capture arguments allowing variables to be used as Functions.
The below example contains two variations of a macro that can be used to easily generate different encounter types with minimal repetative scripting whilst also avoiding the use of inefficient calls to functions.
Macro's must be defined prior to delayed expansion being enabled as variables referenced during macro execution are defined using ! expansion so that the value the macro is parsed with at expansion is the value of the variable at the time of parsing, not it's value during definition.
#echo off
mode con cols=110 lines=32
(Set \n=^^^
%= macro newline DNR =%
)
(Set LF=^
%= Linefeed DNR =%)
rem Example 1: npc generation; Fixed Formula macro
rem USAGE: %npc{generic}%{Npc name / type}{npc max level}{npc multiplier}{damage value or formula}
Set npc{generic}=For %%n in (1 2)Do if %%n==2 (%\n%
For /F "Tokens=1,2,3,4 Delims={}" %%G in ("!Params!")Do (%\n%
Set "npctype=%%G" %\n%
Set /a "npclvl= !random! %% %%H + 1" %\n%
Set /a "npchp= !npclvl! * %%I" %\n%
Set /a "npcdmg= %%J" %\n%
Set /a "npcdef= ( !npchp! * %%H ) / %%I" %\n%
Set /a "npcxp=!npclvl! * %%I" %\n%
echo/Enemy: !npctype!!LF!level: !npclvl!!LF!HP: !npchp!!LF!Damage: !npcdmg!!LF!Defence: !npcdef!!LF!XP: !npcxp!!LF!%\n%
)%\n%
) Else Set Params=
rem Example 2: npc generation; Supplied Formula macro
rem USAGE: %npc{boss}%{Npc name / type}{level value or formula}{hp value or formula}{damage value or formula}{defense value or formula}{xp value or formula}
Set npc{boss}=For %%n in (1 2)Do if %%n==2 (%\n%
For /F "Tokens=1,2,3,4,5,6 Delims={}" %%G in ("!Params!")Do (%\n%
Set "npctype=%%G" %\n%
Set /a "npclvl= %%H " %\n%
Set /a "npchp= %%I " %\n%
Set /a "npcdmg= %%J " %\n%
Set /a "npcdef= %%K " %\n%
Set /a "npcxp= %%L " %\n%
echo/Enemy: !npctype!!LF!level: !npclvl!!LF!HP: !npchp!!LF!Damage: !npcdmg!!LF!Defence: !npcdef!!LF!XP: !npcxp!!LF!%\n%
)%\n%
) Else Set Params=
rem enable delayed expansion after macro definitions
setlocal enableextensions enabledelayedexpansion
:randomnpc
%npc{generic}%{Wooden Dummy}{5}{100}{0}
Pause
%npc{boss}%{Dragon}{!random! %% 10 + 10}{npclvl * 200}{npchp / 20}{npchp / (npclvl / 2)}{npclvl * 150}
Endlocal
Goto :Eof

Related

Can you use two variables for GEQ comparisons in batch

At the moment I am trying to make a fan-made Pokemon game. I'm making a man who sells poke balls. Here is the code I used to make it. But for some reason, the file fails to execute the last part. Btw I am also a noob at coding. To some extent, at least. Also, I use windows Batch.
#echo off
:setvariables
cls
set/a pokeballs=0
set/a pokemondollar=1000
set/a manprice=500
:Pokeball_Sale
cls
echo How many do you want to buy?
set/p pokeballamount=
set/a totalpokeballprice="pokeballamount * manprice"
echo The price = %totalpokeballprice%
pause
echo Do you want to buy it?
echo Press y for yes
echo Or press n for no
set/p ha=Choose
if %ha% == y goto Payment
if %ha% == n goto Upstairs_House3
:Payment
cls
if "pokemondollar%" GEQ "pokeballprice" set/a pokemondollar-=totalpokeballprice
set/a pokeballs+=pokeballamount
echo You spent %totalpokeballprice% on %pokeballamount%. You now have %pokeballs%.
Aside from the advice you've already been given in the comments, I have decided to post this example, showing a methodology which would make more sense.
#Echo Off
:SetVariables
ClS
Set /A PokeBalls=0,PokemonDollar=1000,ManPrice=500
:PokeBall_Sale
ClS
Set /A PokeBallAmount=0,MaxPokeBalls=PokemonDollar/ManPrice
Set /P "PokeBallAmount=How many Poke Balls do you want to buy [Maximum %MaxPokeBalls%]? "
If %PokeBallAmount% Equ 0 GoTo Upstairs_House3
If %PokeBallAmount% Gtr %MaxPokeBalls% (
Echo You do not have enough funds!
"%__AppDir__%timeout.exe" 3 /NoBreak>NUL
GoTo PokeBall_Sale
)
Set /A TotalPokeBallPrice=PokeBallAmount*ManPrice
"%__AppDir__%choice.exe" /M "The cost is %TotalPokeBallPrice%. Do you want to buy it"
If ErrorLevel 2 GoTo Upstairs_House3
:Payment
ClS
If %PokemonDollar% GEq %TotalPokeBallPrice% (
Echo You spent %TotalPokeBallPrice% on %PokeBallAmount% Poke Balls.
Set /A PokemonDollar-=TotalPokeBallPrice
Set /A PokeBalls+=PokeBallAmount
SetLocal EnableDelayedExpansion
Echo You now have !PokeBalls! Poke Balls and !PokemonDollar! Pokemon Dollars.
EndLocal
"%__AppDir__%timeout.exe" 5 /NoBreak>NUL
)
:Upstairs_House3
ClS
Yes, two Integer variables can indeed be used in Comparisons, so long as they are expanded. Quoting integers for the sake of comparisons is one means to safeguard against invalid variables, another is to make use of Delayed Expansion (Enabled)
There's a great explanation of integer comparison syntax issues here
The below MathCro can be used to assign and modify variables if your interested. In the event an attempt to operate on the 1st Argument with an undeclared variable is made, No change to the variable will occur.
#Echo Off
%= Establish Macros =%
setlocal DisableDelayedExpansion
(set LF=^
%= Newline =%)
Set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"
(Set "Operate=Endlocal ^& Set /A ""%%G%%H=%%I"""
%= 'Tunnels' variable value, Allows Definition of Arithmetic within Macro =%)
Set #M=for /L %%n in (1 1 2) do if %%n==2 (%\n%
for /F "tokens=1,2,3 delims=, " %%G in ("!argv!") do (%\n%
%Operate%%\n%
%= Display value of variable. Optional. If not syntax is required to constrain expansion =%
If Not "!%%G!"=="" Echo(%%G: !%%G!%\n%
) %\n%
) ELSE setlocal enableDelayedExpansion ^& set argv=,
%= script main body =%
%= Facilitate modification of variables within codeblocks. =%
Setlocal EnableDelayedExpansion
REM macro can be used to define as well as modify variables
REM output of macro can be redirected to nul (hidden) like so:
REM (%#M% hp + 50)>nul
%#M% hp + 50
(%#M% heal + 40)>nul
%#M% hp - 30
%#M% hp + 25
%#M% hp * 3
%#M% hp / 2
%#M% hp + heal
%#M% heal - 10
%#M% hp + heal
%= Demonstrates use of an equation beyond the initial Operator. Spaces and parentheses in equation must be ommited =%
%= Increments variable by a random amount in the range of 10 to 20 =%
For /L %%A in (1,1,50) do (%#M% hp + !random!%%10+10)>nul
Echo(hp: %hp%
For /L %%A in (1,1,50) do IF Not !hp! LSS !heal! (%#M% hp - !random!%%15+10)
pause >nul
Exit /B

batch replace spaces between quotes in file and then remove all quotes

I want create a batch to replace spaces with a + sign if the space is in between quotes. Then I want to remove the quotes from a text file. How can I accomplish this?
So I want to change a line like this:
2016-01-11 14:45:09 Server 127.0.0.1 GET /global/images/logo_small.jpg - 80 - 173.252.120.117 "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)" "-" www.vietnam.ttu.edu 200 200 200 1868 0
To this line.
2016-01-11 14:45:09 Server 127.0.0.1 GET /global/images/logo_small.jpg - 80 - 173.252.120.117 facebookexternalhit/1.1+(+http://www.facebook.com/externalhit_uatext.php) - www.vietnam.ttu.edu 200 200 200 1868 0
Thanks
You could use JREPL.BAT to arrive at a very concise and efficient solution. JREPL is a pure script based (JScript/batch) regular expression text processing utility that runs on any version of Windows from XP onward.
jrepl "\q| " "q=!q;''|q?'+':' '" /j /x /t "|" /jbegln "q=false" /f test.txt /o -
For this solution I use the /T option, which is very similar to the unix tr utility, or the sed y command.
I define two search terms, the first for a quote (The \X option enables the \q escape sequence), and the second for a space.
The /J option treats replacement strings as JScript. The first replacement string for the quote toggles a "q" variable TRUE or FALSE, and replaces the quote with an empty string. The second replacement string conditionally replaces the space with a plus or space, depending on the state of the "q" variable.
The /JBEGLN option initializes the "q" variable to FALSE at the beginning of each line.
The /F option specifies the input file, and the /O - option specifies that the output overwrites the original file.
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q34732271.txt"
FOR /f "usebackqdelims=" %%a IN ("%filename1%") DO ECHO %%a&SET "line="&CALL :process %%a
GOTO :EOF
:process
SET "addition=%~1"
IF not DEFINED addition ECHO %line:~1%&GOTO :eof
IF "%~1"==%1 (
REM quoted
SET "line=%line% %addition: =+%"
) ELSE (
SET "line=%line% %addition%"
)
shift
GOTO process
You would need to change the setting of sourcedir to suit your circumstances.
I used a file named q34732271.txt containing your data for my testing.
The echo %%a shows your one line of data on the screen and the echo within the :process routine shows that line processed.
Batch is not an ideal language to process strings as it exhibits sensitivity to many symbols. This process should work provided you are happy to have space-strings compressed and the source string does not contain , ;,tab % or any other symbol that cmd treats specially.
Here is a pure batch-file solution that walks through the characters in each line in file line.txt, replaces all SPACEs in between a pair of quotation marks "" by + signs and stores the result in text_new.txt. The input string may contain any characters, even special ones:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Define global constants here:
set "INFILE=line.txt"
set "OUTFILE=line_new.txt"
set "SEARCH= "
set "REPLACE=+"
set "KEEPQUOTES="
set "QUOTE="""
set "QUOTE=%QUOTE:~,1%"
set "QFLAG="
> "%OUTFILE%" (
for /F usebackq^ delims^=^ eol^= %%L in ("%INFILE%") do (
set "LINE=%%L"
call :SUB LINE
)
)
endlocal
exit /B
:SUB
setlocal EnableDelayedExpansion
set "LINE=!%1!"
set "LINENEW="
set /A "POS=0"
:LOOP
set "CHAR=!LINE:~%POS%,1!"
set /A "POS+=1"
if not defined CHAR (
echo(!LINENEW!
endlocal
exit /B
)
if "!CHAR!"=="!QUOTE!" (
if defined QFLAG (
set "QFLAG="
) else (
set "QFLAG=Quoted"
)
if defined KEEPQUOTES (
set "LINENEW=!LINENEW!!CHAR!"
)
) else if defined QFLAG (
if "!CHAR!"=="!SEARCH!" (
set "LINENEW=!LINENEW!!REPLACE!"
) else (
set "LINENEW=!LINENEW!!CHAR!"
)
) else (
set "LINENEW=!LINENEW!!CHAR!"
)
goto :LOOP

How to limit a batch variable's length

Is it any way to limit the length of a batch variable? I mean, if it is possible to program a variable that only admits between 0 and x characters? So, for an instance, if I entered 123456 and the max length was 4 it wouldn't proceed to continue. I hope you can understand my question.
Thanks in advance.
Demonstration batch code according to suggestions of aschipfl and rojo:
#echo off
setlocal EnableExtensions EnableDelayedExpansion
:UserPrompt
cls
set "UserInput="
set /P "UserInput=Enter string with a length between 1 and 4: "
if not defined UserInput goto UserPrompt
if not "!UserInput:~4!" == "" goto UserPrompt
echo/
echo String entered: !UserInput!
echo/
endlocal
pause
!UserInput:~4! is replaced by command processor on execution of the batch file by the string from user input starting with fifth character. First character of a string value has index value 0 which is reason for number 4 for fifth character. This string is empty if user entered a string not longer than 4 characters, otherwise this substring is not empty resulting in user must input again a string.
Delayed expansion is used to avoid an exit of batch processing caused by a syntax error if the user enters a string containing an odd number of double quotes.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
cls /?
echo /?
endlocal /?
if /?
pause /?
set /?
setlocal /?
If you mean "limit the length of a batch variable when it is read via SET /P command", then you may use the ReadLine subroutine described at this post, that emulates SET /P command using pure Batch file commands, and just insert the maximum length restriction.
#echo off
setlocal
call :ReadNChars string4="Enter 4 characters maximum: " 4
echo String read: "%string4%"
goto :EOF
:ReadNChars var="prompt" maxLen
rem Read a line emulating SET /P command
rem Antonio Perez Ayala
rem Initialize variables
setlocal EnableDelayedExpansion
echo > _
for /F %%a in ('copy /Z _ NUL') do set "CR=%%a"
for /F %%a in ('echo prompt $H ^| cmd') do set "BS=%%a"
rem Show the prompt and start reading
set /P "=%~2" < NUL
set "input="
set i=0
:nextKey
set "key="
for /F "delims=" %%a in ('xcopy /W _ _ 2^>NUL') do if not defined key set "key=%%a"
rem If key is CR: terminate input
if "!key:~-1!" equ "!CR!" goto endRead
rem If key is BS: delete last char, if any
set "key=!key:~-1!"
if "!key!" equ "!BS!" (
if %i% gtr 0 (
set /P "=!BS! !BS!" < NUL
set "input=%input:~0,-1%"
set /A i-=1
)
goto nextKey
)
rem Insert here any filter on the key
if %i% equ %3 goto nextKey
rem Else: show and accept the key
set /P "=.!BS!%key%" < NUL
set "input=%input%%key%"
set /A i+=1
goto nextKey
:endRead
echo/
del _
endlocal & set "%~1=%input%"
exit /B
However, if you want to limit the length of a Batch variable in other cases, like SET /A or plain SET commands, then there is no way to do that. Of course, you may execute such commands and then cut the variable value to the maximum length, but that process is an entirely different thing.

Escape asterisk in Windows Batch File's FOR Loop

When running the following code in a windows batch file everything works aside from the string containing the asterisk, which is skipped. Checking the passed parameters by number (i.e. echo(%~6) I can see the asterisk - it's only when passed to the FOR loop that I have an issue:
#echo off
setlocal enableextensions enabledelayedexpansion
call:Concat cmd "this is a demo" " of concat functionality." " Hopefully it will work;" " but it doesn't when I pass an" " * asterisk" " character"
echo !cmd!
#goto:end
#goto:eof
:Concat
::Concatenates a given list of strings without including their quotes
::1 - output variable
::2* - strings to concat
echo(%*
set /a xx=0
set Concat_tempFlag=0
set Concat_temp=
for %%A in (%*) do (
set /a xx=!xx!+1
echo !xx! - %%A
if !Concat_tempFlag!==1 (
set Concat_temp=!Concat_temp!%%~A
) else (
set Concat_tempFlag=1
)
)
set "%~1="%Concat_temp%""
#goto:eof
:End
echo(Bye
exit /b 0
I've attempted for /F (tokens=*) %%A in ('echo(%*') do ( as suggested here: Batch FOR loop with asterisk (and variations thereof) but with no luck. Any ideas? Thanks in advance.
Found the solution here: I need to match or replace an asterisk * in a batch environmental variable using only native Windows commands. Is this possible?
Full code below:
#echo off
setlocal enableextensions enabledelayedexpansion
set DEFAULT_AsteriskMarker=_xAsteriskMarkerx_
call:Concat cmd "this is a demo" " of concat functionality." " Hopefully it will work;" " but it doesn't when I pass an" " * asterisk" " character"
echo !cmd!
#goto:end
#goto:eof
:Concat
::Concatenates a given list of strings without including their quotes
::1 - output variable
::2* - strings to concat
set Concat_StringsToConcat=%*
echo(%Concat_StringsToConcat%
call:AsteriskFix Concat_StringsToConcat
set /a xx=0
set Concat_tempFlag=0
set Concat_temp=
for %%A in (%Concat_StringsToConcat%) do (
set /a xx=!xx!+1
echo !xx! - %%A
if !Concat_tempFlag!==1 (
set Concat_temp=!Concat_temp!%%~A
) else (
set Concat_tempFlag=1
)
)
set "%~1="!Concat_temp:%DEFAULT_AsteriskMarker%=*!"
#goto:eof
:AsteriskFix
::https://stackoverflow.com/questions/11685375/i-need-to-match-or-replace-an-asterisk-in-a-batch-environmental-variable-using
set AsteriskFix_temp=!%~1!
if "%~2"=="" (
set AsteriskFix_marker=%DEFAULT_AsteriskMarker%
) else (
set AsteriskFix_marker=%~2
)
call:StrLen AsteriskFix_temp AsteriskFix_len
for /l %%x in (0,1,%AsteriskFix_len%) do if not "!AsteriskFix_temp:~%%x,1!"=="" if "!AsteriskFix_temp:~%%x,1!"=="*" (
set /a AsteriskFix_plusone=%%x+1
for /l %%y in (!AsteriskFix_plusone!, 1, !AsteriskFix_plusone!) do (
set AsteriskFix_temp=!AsteriskFix_temp:~0,%%x!%AsteriskFix_marker%!AsteriskFix_temp:~%%y!
)
)
set "%~1=!AsteriskFix_temp!"
#goto:eof
:StrLen
::http://www.dostips.com/DtCodeCmdLib.php#strLen
set "StrLen_str=A!%~1!" &:: keep the A up front to ensure we get the length and not the upper bound
::it also avoids trouble in case of empty string
set "StrLen_len=0"
for /L %%A in (12,-1,0) do (
set /a "StrLen_len|=1<<%%A"
for %%B in (!StrLen_len!) do if "!StrLen_str:~%%B,1!"=="" set /a "StrLen_len&=~1<<%%A"
)
IF "%~2" NEQ "" SET /a %~2=%StrLen_len%
#goto:eof
:End
echo(Bye
exit /b 0
Thanks to James K
The link you provided leads to the right answer:
There is no way to preserve an asterisk (nor a question mark) in the set of a normal (no /F option) FOR command (they are always changed to file names); you need to separate the parameters in a FOR /F command. If you also want to process each parameter in a FOR loop, then the second FOR can NOT be in the same context, so you must CALL a subroutine to change the context

LastIndexOf in Windows batch

I need to implement a function in a Windows batch script to get the LastIndexOf a character into a given string.
For example: Given the following string, I need to get the last index of character '/':
/name1/name2/name3
^
So I need to get the value:
12
Joey's solution works, but the character to find is hard coded, and it is relatively slow.
Here is a parametized function that is fast and can find any character (except nul) within the string. I pass the name of variables containing the string and the character instead of string literals so that the function easily supports all characters.
#echo off
setlocal
set "test=/name1/name2/name3"
set "char=/"
::1st test simply prints the result
call :lastIndexOf test char
::2nd test stores the result in a variable
call :lastIndexOf test char rtn
echo rtn=%rtn%
exit /b
:lastIndexOf strVar charVar [rtnVar]
setlocal enableDelayedExpansion
:: Get the string values
set "lastIndexOf.char=!%~2!"
set "str=!%~1!"
set "chr=!lastIndexOf.char:~0,1!"
:: Determine the length of str - adapted from function found at:
:: http://www.dostips.com/DtCodeCmdLib.php#Function.strLen
set "str2=.!str!"
set "len=0"
for /L %%A in (12,-1,0) do (
set /a "len|=1<<%%A"
for %%B in (!len!) do if "!str2:~%%B,1!"=="" set /a "len&=~1<<%%A"
)
:: Find the last occurrance of chr in str
for /l %%N in (%len% -1 0) do if "!str:~%%N,1!" equ "!chr!" (
set rtn=%%N
goto :break
)
set rtn=-1
:break - Return the result if 3rd arg specified, else print the result
( endlocal
if "%~3" neq "" (set %~3=%rtn%) else echo %rtn%
)
exit /b
It wouldn't take much modification to create a more generic :indexOf function that takes an additional argument specifying which occurance to find. A negative number could specify to search in reverse. So 1 could be the 1st, 2 the 2nd, -1 the last, -2 penultimate, etc.
(Note: I'm assuming Windows batch files because, frankly, I have only seen a single question asking for an actual DOS batch file here so far. Most people simply misattribute “DOS” to anything that has a window of gray-on-black monospaced text without knowing what they're actually talking of.)
Just loop through it, updating the index as you go:
#echo off
setlocal enabledelayedexpansion
set S=/name1/name2/name3
set I=0
set L=-1
:l
if "!S:~%I%,1!"=="" goto ld
if "!S:~%I%,1!"=="/" set L=%I%
set /a I+=1
goto l
:ld
echo %L%
I know this question is a bit old now, but I needed a function that could find the location of a substring (of any length) within a string, and adapted dbenham's solution for my purposes. This function also works with individual characters within a string, as asked for in the original question, and can search for specific instances (as suggested by dbenham).
To use this function, the actual strings must be passed. Dbenham does note that this supports fewer characters than passing the actual variables, but I find that this variant is more reuseable (especially with pipes).
The third argument takes the instance that should be found, with negative numbers specifying to search from the end. The index returned is the offset from the start of the string to the first character in the substring.
#ECHO off
SET search_string=sub
CALL :strIndex "The testing subjects subjects to testing." "%search_string%" -2
ECHO %ERRORLEVEL%
PAUSE
EXIT
:strIndex string substring [instance]
REM Using adaptation of strLen function found at http://www.dostips.com/DtCodeCmdLib.php#Function.strLen
SETLOCAL ENABLEDELAYEDEXPANSION
SETLOCAL ENABLEEXTENSIONS
IF "%~2" EQU "" SET Index=-1 & GOTO strIndex_end
IF "%~3" EQU "" (SET Instance=1) ELSE (SET Instance=%~3)
SET Index=-1
SET String=%~1
SET "str=A%~1"
SET "String_Length=0"
FOR /L %%A IN (12,-1,0) DO (
SET /a "String_Length|=1<<%%A"
FOR %%B IN (!String_Length!) DO IF "!str:~%%B,1!"=="" SET /a "String_Length&=~1<<%%A"
)
SET "sub=A%~2"
SET "Substring_Length=0"
FOR /L %%A IN (12,-1,0) DO (
SET /a "Substring_Length|=1<<%%A"
FOR %%B IN (!Substring_Length!) DO IF "!sub:~%%B,1!"=="" SET /a "Substring_Length&=~1<<%%A"
)
IF %Substring_Length% GTR %String_Length% GOTO strIndex_end
SET /A Searches=%String_Length%-%Substring_Length%
IF %Instance% GTR 0 (
FOR /L %%n IN (0,1,%Searches%) DO (
CALL SET StringSegment=%%String:~%%n,!Substring_Length!%%
IF "%~2" EQU "!StringSegment!" SET /A Instance-=1
IF !Instance! EQU 0 SET Index=%%n & GOTO strIndex_end
)) ELSE (
FOR /L %%n IN (%Searches%,-1,0) DO (
CALL SET StringSegment=%%String:~%%n,!Substring_Length!%%
IF "%~2" EQU "!StringSegment!" SET /A Instance+=1
IF !Instance! EQU 0 SET Index=%%n & GOTO strIndex_end
))
:strIndex_end
EXIT /B %Index%

Resources