<http://www.netikka.net/tsneti/info/tscmd050.htm>
Copyright © 2003- by Prof. Timo Salmi  
Last modified Mon 29-Dec-2014 12:56:08

 
Assorted NT/2000/XP/.. CMD.EXE Script Tricks
From the html version of the tscmd.zip 1cmdfaq.txt file
To the Description and the Index
 

This page is edited from the 1cmdfaq.txt faq-file contained in my tscmd.zip command line interface (CLI) collection. That zipped file has much additional material, including a number of detached .cmd script files. It is recommended that you also get the zipped version as a companion.

Please see "The Description and the Index page" for the conditions of usage and other such information.



50} How do I get the position of a substring in a string?

One potential, pure script solution:
  @echo off & setlocal enableextensions
  rem    01234567890123456789
  set a_=Hello world, Hello.
  set b_=ll
  call :InStrFN "%a_%" "%b_%" position_
  echo The first position of "%b_%" in "%a_%" is %position_%
  endlocal & goto :EOF
  ::
  ::===============================================================
  :: A subroutine to find the first position of a searchstring in a
  :: mainstring. If not found returns -1. If found, the indexing of
  :: the position starts from 0 in accordance with SET conventions.
  ::

  :InStrFN
  setlocal enableextensions enabledelayedexpansion
  ::
  :: Get the mainstring and the searchstring, get rid of possible quotes

  set MainStr=%1
  set MainStr=%MainStr:"=%
  set SearchStr=%2
  set SearchStr=%SearchStr:"=%
  ::
  :: Get the length of the searchstring

  set rest_=%SearchStr%
  set /a SearchLength_=0
  :_length_loop
    set /a SearchLength_+=1
    set rest_=%rest_:~1%
    if defined rest_ goto :_length_loop
  ::
  :: Check for a non-match

  echo %MainStr%|find "%SearchStr%">nul
  if %errorlevel% EQU 1 (endlocal & set /a %3=-1& goto :EOF)
  ::
  :: Match the searchstring with mainstring substrings

  set /a i_=0
  :_position_loop
    if "!MainStr:~%i_%,%SearchLength_%!"=="%SearchStr%" (
      endlocal & set /a %3=%i_%& goto :EOF)
    set /a i_+=1
    goto _position_loop
  endlocal & goto :EOF
 
The output will be
  D:\TEST>cmdfaq
  The first position of "ll" in "Hello world, Hello." is 2

There are other solution options:
  @echo off & setlocal enableextensions enabledelayedexpansion
  set a_=Hello world, Hello.
  set b_=ll
  set instr=-1
  for /l %%i in (0,1,255) do (
    set str=!a_:~%%i!
    if defined str (
      echo !str!|findstr /b /l "%b_%">nul
      if !errorlevel! EQU 0 if !instr! EQU -1 set instr=%%i
      )
    )
  echo The first position of "%b_%" in "%a_%" is %instr%
  endlocal & goto :EOF

To find the last position:
  @echo off & setlocal enableextensions
  set a_=Hello world, Hello.
  set b_=ll
  call :InStrLastFN "%a_%" "%b_%" position_
  echo The last position of "%b_%" in "%a_%" is %position_%
  endlocal & goto :EOF
  ::
  :: ============================================================

  :InStrLastFN
  setlocal enableextensions enabledelayedexpansion
  echo %1|findstr %2>nul
  if %errorlevel% EQU 1 (endlocal & set %3=-1& goto :EOF)
  set rest_=%1
  set /a instr_=-1
  :_loop
    set rest_=%rest_:~1%
    echo !rest_!|findstr %2>nul
    if %errorlevel% EQU 1 (endlocal & set %3=%instr_%& goto :EOF)
    set /a instr_ +=1
    goto _loop
  endlocal & goto :EOF

The output will be
  D:\TEST>cmdfaq
  The last position of "ll" in "Hello world, Hello." is 15

There are other solution options:
  @echo off & setlocal enableextensions enabledelayedexpansion
  set a_=Hello world, Hello.
  set b_=ll
  set instr=-1
  for /l %%i in (0,1,255) do (
    set str=!a_:~%%i!
    if defined str (
      echo !str!|findstr /b /l "%b_%">nul
      if !errorlevel! EQU 0 set instr=%%i
      )
    )
  echo The last position of "%b_%" in "%a_%" is %instr%
  endlocal & goto :EOF

If you can get hold of QBASIC, the first position can also be solved as follows
  @echo off & setlocal enableextensions
  if defined ProgramW6432 (
    echo/
    echo Exiting: %~f0 is incompatible with 64-bit Windows
    goto :EOF)
  ::
  set a_=Hello world, Hello.
  set b_=ll
  ::
  > tmp$$$.bas echo OPEN "tmp$$$.cmd" FOR OUTPUT AS #1
  >>tmp$$$.bas echo PRINT #1, "@set p_=";LTRIM$(STR$(INSTR("%a_%", "%b_%")))
  >>tmp$$$.bas echo CLOSE #1
  >>tmp$$$.bas echo SYSTEM
  ::
  qbasic /run tmp$$$.bas
  call tmp$$$.cmd
  ::
  echo The position of "%b_%" in "%a_%" is %p_%
  ::
  for %%f in (tmp$$$.bas tmp$$$.cmd) do if exist %%f del %%f
  endlocal & goto :EOF

The output will be (note the different indexing!)
  D:\TEST>cmdfaq
  The position of "ll" in "Hello world, Hello." is 3

Alternatively, a Visual Basic aided command line script solution could be used:
  @echo off & setlocal enableextensions
  :: Build a Visual Basic Script
  findstr "'VBS" "%~f0"|findstr /v "findstr" > tmp$$$.vbs
  ::
  set a_=Hello world, Hello.
  set b_=ll
  ::
  :: Run the Visual Basic Script

  cscript //nologo tmp$$$.vbs
  ::
  :: Run the auxiliary CMD script

  call tmp$$$.cmd
  ::
  echo The position of "%b_%" in "%a_%" is %p_%
  ::
  for %%f in (tmp$$$.vbs tmp$$$.cmd) do if exist %%f del %%f
  endlocal & goto :EOF
  '
  '................................................................
  'The Visual Basic Script
  '

  Const ForReading = 1, ForWriting = 2, ForAppending = 8 'VBS
  Dim a, b, p, FSO, fout 'VBS
  Set WshShell = WScript.CreateObject("WScript.shell") 'VBS
  a=WshShell.ExpandEnvironmentStrings("%a_%") 'VBS
  b=WshShell.ExpandEnvironmentStrings("%b_%") 'VBS
  p = InStr(1, a, b, vbTextCompare) 'VBS
  Set FSO = CreateObject("Scripting.FileSystemObject") 'VBS
  Set fout = FSO.OpenTextFile("tmp$$$.cmd", ForWriting, true) 'VBS
  fout.WriteLine "@set p_=" & p 'VBS

The output would (again) be
  D:\TEST>cmdfaq
  The position of "ll" in "Hello world, Hello." is 3

More concisely
  @echo off & setlocal enableextensions
  :: Build a Visual Basic Script
  set vbs_=%temp%\tmp$$$.vbs
  set skip=
  findstr "'%skip%VBS" "%~f0" > "%vbs_%"
  ::
  set a_=Hello world, Hello.
  set b_=ll
  ::
  :: Run the Visual Basic Script

  for /f %%p in ('
    cscript //nologo "%vbs_%" "%a_%" "%b_%"') do (
      set p_=%%p)
  :: Clean up
  for %%f in ("%vbs_%") do if exist %%f del %%f
  ::
  :: Display the result

  echo The position of "%b_%" in "%a_%" is %p_%
  endlocal & goto :EOF
  '
  '...............................................
  'The Visual Basic Script
  '

  set arg = WScript.Arguments 'VBS
  a = arg(0) 'VBS
  b = arg(1) 'VBS
  Wscript.Echo InStr(1, a, b, 1) 'VBS

Or even more concisely
  @echo off & setlocal enableextensions
  ::
  set a_=Hello world, Hello.
  set b_=ll
  ::
  :: Build and run a Visual Basic Script

  set vbs_=%temp%\tmp$$$.vbs
  >"%vbs_%" echo Wscript.Echo InStr(1, "%a_%", "%b_%", 1)
  for /f %%p in ('cscript //nologo "%vbs_%"') do set p_=%%p
  for %%f in ("%vbs_%") do if exist %%f del %%f
  ::
  :: Display the result

  echo The position of "%b_%" in "%a_%" is %p_%
  endlocal & goto :EOF

References/Comments: (If a Google message link fails try the links within the brackets.)
  Google Groups Jan 4 2004, 1:30 am [M]