使用批处理文件从字符串(文件名)中提取特定部分
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 意外结果
我正在尝试提取当前目录中所有文件名(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 意外结果