使用批处理文件从字符串(文件名)中提取特定部分

时间:2016-09-27 08:05:00

标签: batch-file cmd substring delayedvariableexpansion

我正在尝试提取当前目录中所有文件名(pdf文件)的一部分。

文件名的长度因最后一部分(日期时间和扩展名)而异,但总是16个字符。剩下的部分总是有不同的长度。即使我要求的部分也可能有不同的长度。

我尝试使用获得here的lastIndexOf函数。

filename例如:academyo-nonpo- 2582365 -082416051750.pdf

我想以Bold的形式提取部分。 我尝试修剪最后17个字符(这部分总是有一个固定的长度。)然后尝试获取最后一个索引 - '(因为第一部分可以有可变的字符长度。)和修剪字符直到该位置,该位置应返回文件名的所需部分。

@echo off
Setlocal enabledelayedexpansion

For %%# in ("%~dp0\*.pdf") Do (
    Set "File=%%~nx#"
    Set "File=!File:~0,-17!"
    Set "lio2="
    @echo on
    echo !File!
    @echo off
    call :lastindexof !File! - lio2
    Set "File=!File:~%lio%!"

)

Pause&Exit

:lastindexof [%1 - string ; %2 - find last index of ; %3 - if defined will store the result in variable with same name]
@echo off
setlocal enableDelayedExpansion 


set "str=%~1"
set "p=!str:%~2=&echo.!"
set "splitter=%~2"

set LF=^


rem ** Two empty lines are required
echo off
for %%L in ("!LF!") DO (
    for /f "delims=" %%R in ("!splitter!") do ( 
        set "var=!str:%%R=%%L!"
    )
)

for /f  delims^=^" %%P in ("!var!") DO ( 
    set "last_part=%%~P"  
)

if "!last_part!" equ ""  if "%~3" NEQ "" (
 echo "not contained" >2 
 endlocal
 set %~3=-1 
 exit
) else (
 echo "not contained" >2 
 endlocal

set argv=original
set $strLen=for /L %%n in (1 1 2) do if %%n==2 (%\n%
      for /F "tokens=1,2 delims=, " %%1 in ("!argv!") do (%\n%
         set "str=A!%%~2!"%\n%
    echo -1 
)
setlocal DisableDelayedExpansion

set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"
        set "len=0"%\n%
           for /l %%A in (12,-1,0) do (%\n%
             set /a "len|=1<<%%A"%\n%
             for %%B in (!len!) do if "!str:~%%B,1!"=="" set /a "len&=~1<<%%A"%\n%
           )%\n%
           for %%v in (!len!) do endlocal^&if "%%~b" neq "" (set "%%~1=%%v") else echo %%v%\n%
      ) %\n%
) ELSE setlocal enableDelayedExpansion ^& set argv=,


%$strlen% strlen,str
%$strlen% plen,last_part
%$strlen% slen,splitter

set /a lio=strlen-plen-slen
endlocal & if "%~3" NEQ "" (set %~3=%lio%) else echo %lio%
exit /b

作为第3个参数传递给函数的变量的引用似乎没有返回所需的值。 我不知道这里有什么问题。

3 个答案:

答案 0 :(得分:0)

要以粗体显示该部分,请执行以下操作:

实施例#

@Echo Off
SetLocal EnableDelayedExpansion
For %%# in ("%~dp0*.pdf") Do (
    Set "File=%%~n#"
    Set "File=!File:~-20,7!"
    Echo=!File!%%~x#)
Pause

好的呢?

@Echo Off
SetLocal EnableDelayedExpansion
For %%# in ("%~dp0*.pdf") Do (
    Set "File=%%~n#"
    Set "File=!File:~,-13!"
    Call :Sub "!File:-=\!%%~x#")
Pause
:Sub
Echo=%~nx1

答案 1 :(得分:0)

查看this answer。我们首先要计算令牌的数量(你仍然需要在此之前修剪字符串),然后获取最后一个令牌。

在显示"tokens=1*"的第一个循环中,您必须将其编辑为以下内容:"tokens=1* delims=-",并在第二个循环中添加delims=-以及%i%之后。它应该与您的脚本完全相同:

@echo off
SetLocal EnableDelayedExpansion

For %%# in ("%~dp0\*.pdf") Do (
Set "File=%%~nx#"
Set "File=!File:~0,-17!"
Set "lio2="
@echo on
echo !File!
@echo off
call:subfunction !File! - lio2
Set "File=!File:~%lio%!"
)

:subfunction
set var1=%1
set var2=%var1%
set i=0

:loopprocess
for /F "tokens=1* delims=-" %%A in ( "%var1%" ) do (
  set /A i+=1
  set var1=%%B
  goto loopprocess )

for /F "tokens=%i% delims=-" %%G in ( "%var2%" ) do set last=%%G

echo %last%
    REM do what you want with last here!

我测试了它,即使使用类似ac-ade-myo-n-on-po-15482729242321654-082416051750.pdf的内容也似乎正常工作,但是在正确完成后,它会出现一次错误消息,语法错误我无法找到...

如果您可以忽略该错误(其他一切正常),这可能会有所帮助。

答案 2 :(得分:0)

要提取最后一个连字符和倒数第二个连字符之间的部分,可以使用以下脚本(提供字符串/文件作为命令行参数):

@echo off
setlocal EnableExtensions EnableDelayedExpansion

set "SEP=-"

for %%A in (%*) do (
    set "ITEM=%%~A"
    set "PREV="
    if defined ITEM (
        for %%B in ("!ITEM:%SEP%=" "!") do (
            set "PREV=!PART!"
            set "PART=%%~B"
        )
        if defined PREV (
            echo(!PREV!
        )
    )
)

endlocal
exit /B

此方法基本上用标准-标记化字符 SPACE 替换每个cmd,并使用标准for循环遍历生成的字符串(no {{ 1}}选项)。当前迭代的部分存储在变量/F中,其内容首先被复制到PART以获得一次循环迭代的延迟。所以倒数第二部分最终存储在PREV

请注意,如果字符串/文件因delayed expansion而包含感叹号,则此脚本可能会返回意外结果。