5

我需要在 Windows 批处理脚本中实现一个函数,以将 LastIndexOf 字符转换为给定的字符串。

例如:给定以下字符串,我需要获取字符的最后一个索引'/'

/name1/name2/name3
            ^

所以我需要获得价值:

12
4

3 回答 3

8

Joey 的解决方案有效,但要查找的字符是硬编码的,而且速度相对较慢。

这是一个快速的参数化函数,可以在字符串中找到任何字符(nul 除外)。我传递包含字符串和字符的变量名而不是字符串文字,以便函数轻松支持所有字符。

@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

创建一个更通用的:indexOf函数不需要太多修改,该函数需要一个额外的参数来指定要查找的事件。负数可以指定反向搜索。所以 1 可能是第一个,2 是第二个,-1 最后一个,-2 倒数第二个,等等。

于 2012-10-22T14:37:41.557 回答
6

(注意:我假设是 Windows 批处理文件,因为坦率地说,到目前为止,我只看到一个问题询问实际的DOS 批处理文件。大多数人只是将“DOS”错误地归因于任何具有灰色窗口的东西——黑色等宽文本,不知道他们实际上在说什么。)

只需遍历它,随时更新索引:

@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%
于 2012-10-22T10:29:05.353 回答
0

我知道这个问题现在有点老了,但我需要一个函数来找到字符串中子字符串(任意长度)的位置,并根据我的目的调整 dbenham 的解决方案。此功能还适用于字符串中的单个字符,如原始问题中所要求的那样,并且可以搜索特定实例(如 dbenham 所建议的那样)。

要使用此函数,必须传递实际的字符串。Dbenham 确实注意到,与传递实际变量相比,它支持的字符更少,但我发现这种变体更可重用(尤其是使用管道)。

第三个参数采用应该找到的实例,负数指定从末尾开始搜索。返回的索引是从字符串开头到子字符串中第一个字符的偏移量。

@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%
于 2014-04-08T05:29:00.953 回答