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

Extract a specific portion from a string(filename) using batch file

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

除了最后一部分(日期时间和扩展名)始终为 16 个字符外,文件名的长度各不相同。其余部分将始终具有不同的长度。即使我需要的部分也可能有不同的长度。

我尝试使用 lastIndexOf 函数获得 here

文件名例如 : academyo-nonpo-2582365-082416051750.pdf

我想提取粗体部分。 我首先尝试 trimming 最后 17 个字符(这部分将始终具有固定长度。),然后尝试获取“-”的最后一个索引(因为第一部分可以具有可变字符长度。)和 trim 到该位置的字符,应该 return 文件名的所需部分。

@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 个参数传递给函数的变量的引用似乎不是 return 所需的值。 我不知道这里出了什么问题。

要获取粗体部分,则:

例子#

@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

看看this answer。思路是先统计token的个数(还是要trim之前的字符串)然后取最后一个token。

在显示 "tokens=1*" 的第一个循环中,您必须将其编辑为以下内容: "tokens=1* delims=-" 并在第二个循环中在 [=14= 之后添加 delims=- ].您的脚本应该看起来像这样:

@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 之类的东西,它似乎也能正常工作,但是在正确完成后,它给出了一条错误消息,其中有一次我找不到语法错误...

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

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

@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

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

请注意,如果 strings/files 由于 delayed expansion.

而包含感叹号,此脚本可能会 return 意外结果