2012-10-22 47 views
4

我需要在Windows批處理腳本中實現一個函數,以將LastIndexOf字符轉換爲給定的字符串。LastIndexOf在Windows批處理

例如:給出下面的字符串,我需要獲得字符'/'的最後一個索引:

/name1/name2/name3 
      ^

所以我需要得到的值:

12 

回答

6

(注:我假設Windows批處理文件,因爲坦率地說,我只看到一個單一的問題,在這裏要求一個實際的DOS批處理文件。大多數人只是簡單地將「DOS」錯誤地分配給任何具有灰色窗口的東西-on黑等寬的文本,而不知道什麼他們實際上談論的)

通過它只是循環,更新索引,當您去:

@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% 
+0

該代碼工作正常,但我創建了一個函數使用您的代碼,函數打印結果,但從不返回,你知道爲什麼嗎?謝謝你的幫助! –

+0

由於我沒有看到你的代碼,我不知道爲什麼它不會返回。但是,我知道它爲什麼要打印結果:您仍然在那裏有「回聲」。至於爲什麼它不返回我只能猜測。我的猜測是你沒有寫一個函數,只是用'goto'而不是'call:label'來調用標籤。 – Joey

+0

+1;一個簡單直接的解決方案,雖然相對較慢。 – dbenham

8

喬伊的解決方案工作,但要找到字符是硬編碼的,並且相對較慢。

這是一個快速的參數化函數,可以在字符串中找到任何字符(除了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可能是第一,第二,第二,-1倒數第二,等等。

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%