Wednesday 19 August 2009

Substring extraction by CMD

Once i needed to solve the next task. I have a batch script with name corresponding to the following conditions:
  1. the script filename has to be matched the pattern (see below).
  2. this script has to be located within directory tree of free nestion but one of directories of the tree has to be macthed the same pattern.
Let's consider the pattern is ABCxxx, where ABC is fixed portion, and xxx is arbitrary and optional one. There are several examples with ABC, ABC1, ABCXYZ looked for:
C:\Documents and Settings\USER\Apps\ABC\bin\script.bat
C:\Documents and Settings\USER\Apps\ABC1\script.bat
C:\Apps\ABC1.bat
C:\Apps\ABCXYZ.bat
Unfortunately, BAT/CMD does not have appropriate tools dealing with substring, patterns, etc. I do not consider so primitive commands like set. This is ok within UNIX environment or in the more progressive languages, but my goal was to implement this feature by BAT/CMD only (of course, if it is available). I have believed that i can realize it. And i was not mistaken. The code below is subroutine accepting four arguments. Three of them are mandatory - the variable name where result will be stored, the pattern, the string to be parsed. The last argument is optional. It is used to provide options for findstr.
rem failed - exact match, case-sensitive
call :subpath SUBPATH users "C:\Documents and Settings\All Users\Start Menu"
echo result = %SUBPATH%

rem successful - case-insensitive - /i option
call :subpath SUBPATH users "C:\Documents and Settings\All Users\Start Menu" /i
echo result = %SUBPATH%

rem successful - case-sensitive
call :subpath SUBPATH Users "C:\Documents and Settings\All Users\Start Menu"
echo result = %SUBPATH%

rem failed - tested portion should start with the pattern - /b option
call :subpath SUBPATH Users "C:\Documents and Settings\All Users\Start Menu" /b
echo result = %SUBPATH%

goto :EOF

:: Extract the first matching to a pattern
::
:: @param  String  variable name
:: @param  String  pattern
:: @param  String  pathname or/and filename
:: @param  String  (optional) arguments for FINDSTR
:subpath
set %~1=
for /f "delims=\ tokens=1,*" %%a in ( "%~3" ) do (
    echo %%~a|findstr %~4 "%~2" > nul
    if errorlevel 1 (
        call :subpath "%~1" "%~2" "%%~b" "%~4"
    ) else (
        set %~1=%%~a
    )
    if defined %~1 goto :EOF
)
goto :EOF

1 comment:

  1. @Echo Off

    Set a=qwertyuiop
    Set b=1
    Set c=2

    Call Set d=%%a:~%b%,%c%%%
    Echo %d%

    ReplyDelete